From d5e625dc2909f309676b05ac1743ea814cef7120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Shaun=20L=C3=BCdeke?= <77498048+shaunluedeke@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:30:12 +0200 Subject: [PATCH 1/7] Add password support for SSH connections Introduced a password parameter to the Ssh class constructor to enable login with a password. Modified related methods to include the password in the SSH and SCP commands. Added a test case to verify password login functionality and updated snapshots accordingly. --- src/Ssh.php | 22 +++++++++++++++---- tests/SshTest.php | 7 ++++++ ...hTest__it_can_login_with_a_password__1.txt | 3 +++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 tests/__snapshots__/SshTest__it_can_login_with_a_password__1.txt diff --git a/src/Ssh.php b/src/Ssh.php index d4561e3..c78647e 100755 --- a/src/Ssh.php +++ b/src/Ssh.php @@ -21,8 +21,9 @@ class Ssh protected Closure $onOutput; private int $timeout = 0; + protected ?string $password = null; - public function __construct(?string $user, string $host, int $port = null) + public function __construct(?string $user, string $host, int $port = null, ?string $password = null) { $this->user = $user; @@ -32,6 +33,8 @@ public function __construct(?string $user, string $host, int $port = null) $this->usePort($port); } + $this->password = $password; + $this->addBash = true; $this->processConfigurationClosure = fn (Process $process) => null; @@ -152,6 +155,14 @@ public function removeBash(): self return $this; } + protected function getPasswordCommand(): string + { + if ($this->password !== null) { + return 'sshpass -p \'' . $this->password . '\' '; + } + return ''; + } + /** * @param string|array $command * @@ -173,9 +184,10 @@ public function getExecuteCommand($command): string return $commandString; } + $passwordCommand = $this->getPasswordCommand(); $bash = $this->addBash ? "'bash -se'" : ''; - return "ssh {$extraOptions} {$target} {$bash} << \\$delimiter".PHP_EOL + return "{$passwordCommand}ssh {$extraOptions} {$target} {$bash} << \\$delimiter".PHP_EOL .$commandString.PHP_EOL .$delimiter; } @@ -206,7 +218,8 @@ public function executeAsync($command): Process public function getDownloadCommand(string $sourcePath, string $destinationPath): string { - return "scp {$this->getExtraScpOptions()} {$this->getTargetForScp()}:$sourcePath $destinationPath"; + $passwordCommand = $this->getPasswordCommand(); + return "{$passwordCommand}scp {$this->getExtraScpOptions()} {$this->getTargetForScp()}:$sourcePath $destinationPath"; } public function download(string $sourcePath, string $destinationPath): Process @@ -218,7 +231,8 @@ public function download(string $sourcePath, string $destinationPath): Process public function getUploadCommand(string $sourcePath, string $destinationPath): string { - return "scp {$this->getExtraScpOptions()} $sourcePath {$this->getTargetForScp()}:$destinationPath"; + $passwordCommand = $this->getPasswordCommand(); + return "{$passwordCommand}scp {$this->getExtraScpOptions()} $sourcePath {$this->getTargetForScp()}:$destinationPath"; } public function upload(string $sourcePath, string $destinationPath): Process diff --git a/tests/SshTest.php b/tests/SshTest.php index 2ab1cbe..5fde7c6 100644 --- a/tests/SshTest.php +++ b/tests/SshTest.php @@ -164,3 +164,10 @@ assertMatchesSnapshot($command); }); + +it('can login with a password', function () { + $ssh = new Ssh('user', 'example.com', 22, 'password'); + $command = $ssh->getExecuteCommand('whoami'); + + assertMatchesSnapshot($command); +}); diff --git a/tests/__snapshots__/SshTest__it_can_login_with_a_password__1.txt b/tests/__snapshots__/SshTest__it_can_login_with_a_password__1.txt new file mode 100644 index 0000000..9ece333 --- /dev/null +++ b/tests/__snapshots__/SshTest__it_can_login_with_a_password__1.txt @@ -0,0 +1,3 @@ +sshpass -p 'password' ssh -p 22 user@example.com 'bash -se' << \EOF-SPATIE-SSH +whoami +EOF-SPATIE-SSH \ No newline at end of file From 5ccca12ef9561537d106493558b094416a0926ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Shaun=20L=C3=BCdeke?= <77498048+shaunluedeke@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:45:53 +0200 Subject: [PATCH 2/7] Add password authentication support for SSH Introduce optional password support in the Ssh class through the constructor and a new usePassword method. Updated README to document these changes and added relevant test cases. --- README.md | 15 ++++++++ src/Ssh.php | 34 +++++++++++++++---- tests/SshTest.php | 7 ++++ ...hTest__it_can_login_with_a_password__1.txt | 3 ++ 4 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 tests/__snapshots__/SshTest__it_can_login_with_a_password__1.txt diff --git a/README.md b/README.md index 9decafc..a339701 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,21 @@ Alternatively you can use the `usePort` function: ```php Ssh::create('user', 'host')->usePort($port); ``` + +### Using a password + +You can use the constructor to specify a password to use. + +```php +Ssh::create('user', 'host', port, 'password'); +``` + +Alternatively you can use the `usePassword` function: + +```php +Ssh::create('user', 'host')->usePassword('password'); +``` + ### Setting a timeout You can set a timeout for the command. diff --git a/src/Ssh.php b/src/Ssh.php index d4561e3..6eed84b 100755 --- a/src/Ssh.php +++ b/src/Ssh.php @@ -22,7 +22,9 @@ class Ssh private int $timeout = 0; - public function __construct(?string $user, string $host, int $port = null) + protected ?string $password = null; + + public function __construct(?string $user, string $host, int $port = null, ?string $password = null) { $this->user = $user; @@ -32,6 +34,8 @@ public function __construct(?string $user, string $host, int $port = null) $this->usePort($port); } + $this->password = $password; + $this->addBash = true; $this->processConfigurationClosure = fn (Process $process) => null; @@ -68,6 +72,13 @@ public function usePort(int $port): self return $this; } + public function usePassword(?string $password): self + { + $this->password = $password; + + return $this; + } + public function useMultiplexing(string $controlPath, string $controlPersist = '10m'): self { $this->extraOptions['control_master'] = '-o ControlMaster=auto -o ControlPath=' . $controlPath . ' -o ControlPersist=' . $controlPersist; @@ -152,6 +163,14 @@ public function removeBash(): self return $this; } + protected function getPasswordCommand(): string + { + if ($this->password !== null) { + return 'sshpass -p \'' . $this->password . '\' '; + } + return ''; + } + /** * @param string|array $command * @@ -173,11 +192,12 @@ public function getExecuteCommand($command): string return $commandString; } + $passwordCommand = $this->getPasswordCommand(); $bash = $this->addBash ? "'bash -se'" : ''; - return "ssh {$extraOptions} {$target} {$bash} << \\$delimiter".PHP_EOL - .$commandString.PHP_EOL - .$delimiter; + return "{$passwordCommand}ssh {$extraOptions} {$target} {$bash} << \\$delimiter".PHP_EOL + .$commandString.PHP_EOL + .$delimiter; } /** @@ -206,7 +226,8 @@ public function executeAsync($command): Process public function getDownloadCommand(string $sourcePath, string $destinationPath): string { - return "scp {$this->getExtraScpOptions()} {$this->getTargetForScp()}:$sourcePath $destinationPath"; + $passwordCommand = $this->getPasswordCommand(); + return "{$passwordCommand}scp {$this->getExtraScpOptions()} {$this->getTargetForScp()}:$sourcePath $destinationPath"; } public function download(string $sourcePath, string $destinationPath): Process @@ -218,7 +239,8 @@ public function download(string $sourcePath, string $destinationPath): Process public function getUploadCommand(string $sourcePath, string $destinationPath): string { - return "scp {$this->getExtraScpOptions()} $sourcePath {$this->getTargetForScp()}:$destinationPath"; + $passwordCommand = $this->getPasswordCommand(); + return "{$passwordCommand}scp {$this->getExtraScpOptions()} $sourcePath {$this->getTargetForScp()}:$destinationPath"; } public function upload(string $sourcePath, string $destinationPath): Process diff --git a/tests/SshTest.php b/tests/SshTest.php index 2ab1cbe..5fde7c6 100644 --- a/tests/SshTest.php +++ b/tests/SshTest.php @@ -164,3 +164,10 @@ assertMatchesSnapshot($command); }); + +it('can login with a password', function () { + $ssh = new Ssh('user', 'example.com', 22, 'password'); + $command = $ssh->getExecuteCommand('whoami'); + + assertMatchesSnapshot($command); +}); diff --git a/tests/__snapshots__/SshTest__it_can_login_with_a_password__1.txt b/tests/__snapshots__/SshTest__it_can_login_with_a_password__1.txt new file mode 100644 index 0000000..9ece333 --- /dev/null +++ b/tests/__snapshots__/SshTest__it_can_login_with_a_password__1.txt @@ -0,0 +1,3 @@ +sshpass -p 'password' ssh -p 22 user@example.com 'bash -se' << \EOF-SPATIE-SSH +whoami +EOF-SPATIE-SSH \ No newline at end of file From 73d5de7d022baa61b842bda1901cb515c893613d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Shaun=20L=C3=BCdeke?= <77498048+shaunluedeke@users.noreply.github.com> Date: Tue, 8 Oct 2024 17:39:49 +0200 Subject: [PATCH 3/7] Rename package to shaunluedeke/ssh Changed the package name in composer.json from spatie/ssh to shaunluedeke/ssh. This update is necessary to reflect the new ownership or namespace of the package. All other metadata remains unchanged. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4bd1796..dcf8e76 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "spatie/ssh", + "name": "shaunluedeke/ssh", "description": "A lightweight package to execute commands over an SSH connection", "keywords": [ "spatie", From 485cd56dbba229c23af5f586eba2def34d8acc9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Shaun=20L=C3=BCdeke?= <77498048+shaunluedeke@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:50:44 +0200 Subject: [PATCH 4/7] Aktualisieren von composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index dcf8e76..4bd1796 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "shaunluedeke/ssh", + "name": "spatie/ssh", "description": "A lightweight package to execute commands over an SSH connection", "keywords": [ "spatie", From 07bfd9cb5d27b0beb7feb3664d6ded5a71043c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Shaun=20L=C3=BCdeke?= <77498048+shaunluedeke@users.noreply.github.com> Date: Fri, 18 Oct 2024 20:13:32 +0200 Subject: [PATCH 5/7] Update SshTest.php --- tests/SshTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/SshTest.php b/tests/SshTest.php index 5fde7c6..7e2f37d 100644 --- a/tests/SshTest.php +++ b/tests/SshTest.php @@ -171,3 +171,10 @@ assertMatchesSnapshot($command); }); + +it('can login with a password failed', function () { + $ssh = new Ssh('user', 'example.com', 22, 'wrong_password'); + $command = $ssh->getExecuteCommand('whoami'); + + assertMatchesSnapshot($command); +}); From b90003ed2cb968c8db16e3f559122967bd3b4cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Shaun=20L=C3=BCdeke?= <77498048+shaunluedeke@users.noreply.github.com> Date: Fri, 18 Oct 2024 20:16:03 +0200 Subject: [PATCH 6/7] Create SshTest__it_can_login_with_a_password_failed__1.txt --- .../SshTest__it_can_login_with_a_password_failed__1.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/__snapshots__/SshTest__it_can_login_with_a_password_failed__1.txt diff --git a/tests/__snapshots__/SshTest__it_can_login_with_a_password_failed__1.txt b/tests/__snapshots__/SshTest__it_can_login_with_a_password_failed__1.txt new file mode 100644 index 0000000..a018274 --- /dev/null +++ b/tests/__snapshots__/SshTest__it_can_login_with_a_password_failed__1.txt @@ -0,0 +1,3 @@ +sshpass -p 'wrong_password' ssh -p 22 user@example.com 'bash -se' << \EOF-SPATIE-SSH +whoami +EOF-SPATIE-SSH From 4e9503d31be0812fdd86e18f48a0920293795b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Shaun=20L=C3=BCdeke?= <77498048+shaunluedeke@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:57:45 +0200 Subject: [PATCH 7/7] Fix newline formatting in SSH test snapshot --- .../SshTest__it_can_login_with_a_password_failed__1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/__snapshots__/SshTest__it_can_login_with_a_password_failed__1.txt b/tests/__snapshots__/SshTest__it_can_login_with_a_password_failed__1.txt index a018274..6e9f86d 100644 --- a/tests/__snapshots__/SshTest__it_can_login_with_a_password_failed__1.txt +++ b/tests/__snapshots__/SshTest__it_can_login_with_a_password_failed__1.txt @@ -1,3 +1,3 @@ sshpass -p 'wrong_password' ssh -p 22 user@example.com 'bash -se' << \EOF-SPATIE-SSH whoami -EOF-SPATIE-SSH +EOF-SPATIE-SSH \ No newline at end of file