From 00265fb0775dcba90153c63912a09f449f49bdbb Mon Sep 17 00:00:00 2001 From: Alexander Hank Date: Wed, 21 Dec 2022 08:56:21 +0100 Subject: [PATCH] Improved architecture --- src/Adapters/Contract/Credential.php | 8 ++++ src/Adapters/SshAdapter/Adapter.php | 43 +++++++++-------- src/Adapters/SshAdapter/Key.php | 3 +- src/Adapters/SshAdapter/Password.php | 20 ++++++++ tests/Adapters/SshAdapter/AdapterTest.php | 58 ++++------------------- 5 files changed, 63 insertions(+), 69 deletions(-) create mode 100644 src/Adapters/Contract/Credential.php create mode 100644 src/Adapters/SshAdapter/Password.php diff --git a/src/Adapters/Contract/Credential.php b/src/Adapters/Contract/Credential.php new file mode 100644 index 0000000..6b79355 --- /dev/null +++ b/src/Adapters/Contract/Credential.php @@ -0,0 +1,8 @@ +connection = $connection; $this->username = $username; + $this->credential = $credential; + $this->publicKey = $publicKey; } @@ -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); } @@ -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'); } } diff --git a/src/Adapters/SshAdapter/Key.php b/src/Adapters/SshAdapter/Key.php index ba40115..5eb47f7 100644 --- a/src/Adapters/SshAdapter/Key.php +++ b/src/Adapters/SshAdapter/Key.php @@ -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; diff --git a/src/Adapters/SshAdapter/Password.php b/src/Adapters/SshAdapter/Password.php new file mode 100644 index 0000000..d386a4b --- /dev/null +++ b/src/Adapters/SshAdapter/Password.php @@ -0,0 +1,20 @@ +password = $password; + } + + public function get(): string + { + return $this->password; + } +} \ No newline at end of file diff --git a/tests/Adapters/SshAdapter/AdapterTest.php b/tests/Adapters/SshAdapter/AdapterTest.php index 17ecd18..f4a11de 100644 --- a/tests/Adapters/SshAdapter/AdapterTest.php +++ b/tests/Adapters/SshAdapter/AdapterTest.php @@ -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; @@ -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()); } @@ -35,7 +34,7 @@ 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()); } @@ -43,65 +42,28 @@ public function it_gets_the_server_public_key() /** * @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); @@ -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()); }