Skip to content

Commit

Permalink
Improved architecture
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexH-HankIT committed Dec 21, 2022
1 parent 6907a86 commit 00265fb
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 69 deletions.
8 changes: 8 additions & 0 deletions src/Adapters/Contract/Credential.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace HankIT\ConsoleAccess\Adapters\Contract;

interface Credential
{
public function get();
}
43 changes: 23 additions & 20 deletions src/Adapters/SshAdapter/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace HankIT\ConsoleAccess\Adapters\SshAdapter;

use Closure;
use HankIT\ConsoleAccess\Adapters\Contract\Credential;
use HankIT\ConsoleAccess\Exceptions\ConnectionNotPossibleException;
use HankIT\ConsoleAccess\Exceptions\PublicKeyMismatchException;
use HankIT\ConsoleAccess\Interfaces\AdapterInterface;
Expand All @@ -14,20 +15,26 @@ class Adapter implements AdapterInterface

protected string $username;

protected Credential $credential;

protected ?string $publicKey;

protected ?string $output = null;

protected bool $initialLogin = false;

public function __construct(
SSH2 $connection,
string $username,
Credential $credential,
?string $publicKey = null
)
{
){
$this->connection = $connection;

$this->username = $username;

$this->credential = $credential;

$this->publicKey = $publicKey;
}

Expand All @@ -41,26 +48,18 @@ public function getServerPublicHostKey(): string
return $this->connection->getServerPublicHostKey();
}

public function loginPassword(string $password): void
public function run(string $command, Closure $live = null): void
{
if (! is_null($this->publicKey) && $this->getServerPublicHostKey() !== $this->publicKey) {
throw new PublicKeyMismatchException('Public key mismatch');
}
if (! $this->initialLogin) {
$this->login();

$this->login($password);
}

public function loginKey(Key $key): void
{
if (! is_null($this->publicKey) && $this->getServerPublicHostKey() !== $this->publicKey) {
throw new PublicKeyMismatchException('Public key mismatch');
$this->initialLogin = true;
}

$this->login($key->get());
}
if (! $this->connection->ping()) {
throw new ConnectionNotPossibleException('Ping failed');
}

public function run(string $command, Closure $live = null): void
{
$this->output = $this->connection->exec($command, $live);
}

Expand All @@ -73,10 +72,14 @@ public function getExitStatus(): int
{
return $this->connection->getExitStatus();
}
protected function login($auth): void

protected function login(): void
{
if (! $this->connection->login($this->username, $auth)) {
if (! is_null($this->publicKey) && $this->getServerPublicHostKey() !== $this->publicKey) {
throw new PublicKeyMismatchException('Public key mismatch');
}

if (! $this->connection->login($this->username, $this->credential->get())) {
throw new ConnectionNotPossibleException('Not connected');
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Adapters/SshAdapter/Key.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

namespace HankIT\ConsoleAccess\Adapters\SshAdapter;

use HankIT\ConsoleAccess\Adapters\Contract\Credential;
use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\PublicKeyLoader;

class Key
class Key implements Credential
{
protected AsymmetricKey $key;

Expand Down
20 changes: 20 additions & 0 deletions src/Adapters/SshAdapter/Password.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace HankIT\ConsoleAccess\Adapters\SshAdapter;

use HankIT\ConsoleAccess\Adapters\Contract\Credential;

class Password implements Credential
{
protected string $password;

public function __construct(string $password)
{
$this->password = $password;
}

public function get(): string
{
return $this->password;
}
}
58 changes: 10 additions & 48 deletions tests/Adapters/SshAdapter/AdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

use Hamcrest\Core\IsEqual;
use HankIT\ConsoleAccess\Adapters\SshAdapter\Adapter;
use HankIT\ConsoleAccess\Adapters\SshAdapter\Key;
use HankIT\ConsoleAccess\Adapters\SshAdapter\Password;
use Mockery;
use phpseclib3\Crypt\EC;
use phpseclib3\Net\SSH2;
use Tests\TestCase;

Expand All @@ -21,7 +20,7 @@ public function it_gets_the_connection_status()

$sshMock->shouldReceive('isConnected')->once()->andReturn(true);

$adapter = new Adapter($sshMock, $this->fake()->userName);
$adapter = new Adapter($sshMock, $this->fake()->userName, new Password('test'));

$this->assertTrue($adapter->available());
}
Expand All @@ -35,73 +34,36 @@ public function it_gets_the_server_public_key()

$sshMock->shouldReceive('getServerPublicHostKey')->once()->andReturn($content = $this->fake()->randomHtml);

$adapter = new Adapter($sshMock, $this->fake()->userName);
$adapter = new Adapter($sshMock, $this->fake()->userName, new Password('test'));

$this->assertEquals($content, $adapter->getServerPublicHostKey());
}

/**
* @test
*/
public function it_tests_the_password_login_without_public_key_verification()
public function it_authenticates_using_a_password_runs_a_command_and_verifies_the_output()
{
$sshMock = Mockery::mock(SSH2::class);

$username = $this->fake()->userName;
$password = $this->fake()->password;
$command = $this->fake()->randomHtml;
$output = $this->fake()->randomHtml;

$sshMock->shouldReceive('login')->withArgs([
IsEqual::equalTo($username),
IsEqual::equalTo($password),
])->once()->andReturnTrue();

$adapter = new Adapter($sshMock, $username);

$adapter->loginPassword($password);
}

/**
* @test
*/
public function it_tests_the_key_login_without_public_key_verification()
{
$sshMock = Mockery::mock(SSH2::class);

$username = $this->fake()->userName;

$key = "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtz\nc2gtZWQyNTUxOQAAACBILfCZGUhmIGgm+5zmcCvvDE4iYwnGx1zsVpOQ24NAjQAA\nAKCE2ZLxhNmS8QAAAAtzc2gtZWQyNTUxOQAAACBILfCZGUhmIGgm+5zmcCvvDE4i\nYwnGx1zsVpOQ24NAjQAAAEC7O4xjSTxQxZcpftnuwdei3EOXxSa1taCHQr5jtUtQ\n1Ugt8JkZSGYgaCb7nOZwK+8MTiJjCcbHXOxWk5Dbg0CNAAAAFGVkMjU1MTkta2V5\nLTIwMjIxMjIxAQIDBAUGBwgJ\n-----END OPENSSH PRIVATE KEY-----";

$sshMock->shouldReceive('login')->withArgs([
IsEqual::equalTo($username),
Mockery::on(function($arg) {
$this->assertInstanceOf(EC::class, $arg);

return true;
})
])->once()->andReturnTrue();

$adapter = new Adapter($sshMock, $username);

$adapter->loginKey(new Key($key));
}

/**
* @test
*/
public function it_runs_a_command_and_verifies_the_output()
{
$sshMock = Mockery::mock(SSH2::class);

$username = $this->fake()->userName;
$command = $this->fake()->randomHtml;
$output = $this->fake()->randomHtml;

$sshMock->shouldReceive('exec')->withArgs([
IsEqual::equalTo($command),
IsEqual::equalTo(null),
])->once()->andReturn($output);

$adapter = new Adapter($sshMock, $username);
$sshMock->shouldReceive('ping')->once()->andReturnTrue();

$adapter = new Adapter($sshMock, $username, new Password($password));

$adapter->run($command);

Expand All @@ -117,7 +79,7 @@ public function it_gets_the_exist_status()

$sshMock->shouldReceive('getExitStatus')->once()->andReturn(0);

$adapter = new Adapter($sshMock, $this->fake()->userName);
$adapter = new Adapter($sshMock, $this->fake()->userName, new Password('test'));

$this->assertEquals(0, $adapter->getExitStatus());
}
Expand Down

0 comments on commit 00265fb

Please sign in to comment.