126 lines
3.5 KiB
PHP
126 lines
3.5 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
use OPNsense\NordVPN\Bootstrapper;
|
||
|
|
use OPNsense\NordVPN\EndpointStore;
|
||
|
|
use OPNsense\NordVPN\ManagedConfiguration;
|
||
|
|
use OPNsense\NordVPN\NordApi;
|
||
|
|
use OPNsense\NordVPN\ReconciliationLock;
|
||
|
|
use OPNsense\NordVPN\Settings;
|
||
|
|
use OPNsense\NordVPN\StatusStore;
|
||
|
|
use OPNsense\NordVPN\SystemRunner;
|
||
|
|
use PHPUnit\Framework\TestCase;
|
||
|
|
|
||
|
|
class BootstrapperTestApi extends NordApi
|
||
|
|
{
|
||
|
|
public string $token = '';
|
||
|
|
private string $key;
|
||
|
|
|
||
|
|
public function __construct(string $key)
|
||
|
|
{
|
||
|
|
$this->key = $key;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function recommendations(array $countryCodes = [], int $limit = 5): array
|
||
|
|
{
|
||
|
|
return [[
|
||
|
|
'hostname' => 'nl.example.invalid',
|
||
|
|
'address' => '198.51.100.10',
|
||
|
|
'country' => 'NL',
|
||
|
|
'public_key' => $this->key,
|
||
|
|
]];
|
||
|
|
}
|
||
|
|
|
||
|
|
public function credentials(string $token): string
|
||
|
|
{
|
||
|
|
$this->token = $token;
|
||
|
|
return $this->key;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class BootstrapperTestConfiguration extends ManagedConfiguration
|
||
|
|
{
|
||
|
|
private Settings $settings;
|
||
|
|
public array $provisioned = [];
|
||
|
|
|
||
|
|
public function __construct()
|
||
|
|
{
|
||
|
|
$this->settings = new Settings();
|
||
|
|
}
|
||
|
|
|
||
|
|
public function settings(): Settings
|
||
|
|
{
|
||
|
|
return $this->settings;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function provision(string $privateKey, array $candidate): void
|
||
|
|
{
|
||
|
|
$this->provisioned = [$privateKey, $candidate];
|
||
|
|
}
|
||
|
|
|
||
|
|
public function repairGatewayInterface(): bool
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class BootstrapperTestRunner extends SystemRunner
|
||
|
|
{
|
||
|
|
public array $operations = [];
|
||
|
|
|
||
|
|
public function applyWireGuard(): void
|
||
|
|
{
|
||
|
|
$this->operations[] = 'wireguard';
|
||
|
|
}
|
||
|
|
|
||
|
|
public function applyRouting(): void
|
||
|
|
{
|
||
|
|
$this->operations[] = 'routing';
|
||
|
|
}
|
||
|
|
|
||
|
|
public function applyFirewall(): void
|
||
|
|
{
|
||
|
|
$this->operations[] = 'firewall';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
final class BootstrapperTest extends TestCase
|
||
|
|
{
|
||
|
|
public function testBootstrapQueuesReconciliationAfterApplyingInitialTunnel(): void
|
||
|
|
{
|
||
|
|
$key = base64_encode(str_repeat("\0", 32));
|
||
|
|
$api = new BootstrapperTestApi($key);
|
||
|
|
$configuration = new BootstrapperTestConfiguration();
|
||
|
|
$runner = new BootstrapperTestRunner();
|
||
|
|
$statusPath = sys_get_temp_dir() . '/nordvpn-bootstrap-' . bin2hex(random_bytes(8)) . '.json';
|
||
|
|
$lockPath = sys_get_temp_dir() . '/nordvpn-bootstrap-' . bin2hex(random_bytes(8)) . '.lock';
|
||
|
|
$endpointDirectory = sys_get_temp_dir() . '/nordvpn-bootstrap-' . bin2hex(random_bytes(8));
|
||
|
|
$endpointPath = $endpointDirectory . '/endpoints.txt';
|
||
|
|
$configuration->settings()->general->exempt_wireguard = '1';
|
||
|
|
$queued = 0;
|
||
|
|
|
||
|
|
$result = (new Bootstrapper(
|
||
|
|
$api,
|
||
|
|
$configuration,
|
||
|
|
new StatusStore($statusPath),
|
||
|
|
$runner,
|
||
|
|
new EndpointStore($endpointPath),
|
||
|
|
new ReconciliationLock($lockPath),
|
||
|
|
static function () use (&$queued): void {
|
||
|
|
$queued++;
|
||
|
|
}
|
||
|
|
))->run('synthetic-token');
|
||
|
|
|
||
|
|
self::assertSame('ok', $result['status']);
|
||
|
|
self::assertSame('synthetic-token', $api->token);
|
||
|
|
self::assertSame($key, $configuration->provisioned[0]);
|
||
|
|
self::assertSame(['firewall', 'wireguard', 'routing', 'firewall'], $runner->operations);
|
||
|
|
self::assertSame("198.51.100.10\n", file_get_contents($endpointPath));
|
||
|
|
self::assertSame('reconciling', $result['tunnel']['state']);
|
||
|
|
self::assertSame(1, $queued);
|
||
|
|
|
||
|
|
unlink($statusPath);
|
||
|
|
unlink($lockPath);
|
||
|
|
unlink($endpointPath);
|
||
|
|
rmdir($endpointDirectory);
|
||
|
|
}
|
||
|
|
}
|