Skip to content

Commit

Permalink
Added support for RSA private key ssh login. Cleaned up SFTP function…
Browse files Browse the repository at this point in the history
…s it use a service to connect.
  • Loading branch information
bobfloats committed May 9, 2016
1 parent 03f6a35 commit 9467766
Show file tree
Hide file tree
Showing 17 changed files with 460 additions and 83 deletions.
Binary file modified Documentation/DatabaseScheme.mwb
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

use VersionControl\GitCommandBundle\GitCommands\GitDiffParser;

use phpseclib\Net\SFTP;

/**
* Description of GitFilesCommand
Expand Down Expand Up @@ -71,13 +70,9 @@ protected function getFileInfo($path){

if($this->command->getGitEnvironment()->getSsh() === true){
//Remote Directory Listing
$sftp = new SFTP($this->command->getGitEnvironment()->getHost(), 22);
if (!$sftp->login($this->command->getGitEnvironment()->getUsername(), $this->command->getGitEnvironment()->getPassword())) {
exit('Login Failed');
}


$fileData = $sftp->stat($basePath.$path);

$fileData = $this->command->getSftpProcess()->getFileStats($basePath.$path);

$fileData['filename'] = basename($path);
$fileData['fullPath'] = $basePath.$path;
$fileData['gitPath'] = $path;
Expand Down Expand Up @@ -162,12 +157,9 @@ public function getFilesInDirectory($dir){

if($this->command->getGitEnvironment()->getSsh() === true){
//Remote Directory Listing
$sftp = new SFTP($this->command->getGitEnvironment()->getHost(), 22);
if (!$sftp->login($this->command->getGitEnvironment()->getUsername(), $this->command->getGitEnvironment()->getPassword())) {
exit('Login Failed');
}
$directoryList = $this->command->getSftpProcess()->getDirectoryList($basePath.$relativePath);

foreach($sftp->rawlist($basePath.$relativePath) as $filename => $fileData) {
foreach($directoryList as $filename => $fileData) {
if($filename !== '.' && $filename !== '..' && $filename !== '.git'){
$fileData['fullPath'] = $basePath.rtrim($relativePath,'/').'/'.$filename;
$fileData['gitPath'] = $relativePath.$filename;
Expand Down Expand Up @@ -203,13 +195,10 @@ public function readFile($file){
$fileContents = '';

if($this->command->getGitEnvironment()->getSsh() === true){
//Remote Directory Listing
$sftp = new SFTP($this->command->getGitEnvironment()->getHost(), 22);
if (!$sftp->login($this->command->getGitEnvironment()->getUsername(), $this->command->getGitEnvironment()->getPassword())) {
exit('Login Failed');
}

$fileContents = $sftp->get($file->getFullPath());


$fileContents = $this->command->getSftpProcess()->getFileContents($file->getFullPath());


}else{
$fileContents = file_get_contents($file->getFullPath());
Expand Down Expand Up @@ -272,14 +261,6 @@ public function setFilesOwnerAndGroup($filePaths,$user ='www-data',$group = 'fr_

}

protected function connectToSftp(){
$sftp = new SFTP($this->command->getGitEnvironment()->getHost(), 22);
if (!$sftp->login($this->command->getGitEnvironment()->getUsername(), $this->command->getGitEnvironment()->getPassword())) {
exit('Login Failed');
}

return $sftp;
}

/**
* Gets the git log (history) of commits
Expand Down Expand Up @@ -356,8 +337,8 @@ public function fileExists($filePath){
$fileExists = false;
$basePath = trim($this->addEndingSlash($this->command->getGitEnvironment()->getPath()));
if($this->command->getGitEnvironment()->getSsh() === true){
$sftp = $this->connectToSftp();
$fileExists = $sftp->file_exists($basePath.$filePath);
$fileExists = $this->command->getSftpProcess()->fileExists($basePath.$filePath);

}else{
$fileExists = file_exists($basePath.$filePath);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the GitCommandBundle package.
*
* (c) Paul Schweppe <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace VersionControl\GitCommandBundle\GitCommands\Exception;

/**
* InvalidArgumentException.
*
* @author Paul Schweppe <[email protected]>
*/
class SshLoginException extends \Exception implements ExceptionInterface
{

}
31 changes: 30 additions & 1 deletion src/VersionControl/GitCommandBundle/GitCommands/GitCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Symfony\Component\Stopwatch\Stopwatch;

use VersionControl\GitCommandBundle\Service\SshProcessInterface;
use VersionControl\GitCommandBundle\Service\SftpProcessInterface;
use VersionControl\GitCommandBundle\GitCommands\Command as Command;
use VersionControl\GitCommandBundle\GitCommands\Exception\InvalidArgumentException;
use VersionControl\GitCommandBundle\Logger\GitCommandLogger;
Expand Down Expand Up @@ -69,6 +70,12 @@ class GitCommand {
*/
private $sshProcess;

/**
* Sftp Process
* @var \VersionControl\GitCommandBundle\Service\SftpProcessInterface
*/
private $sftpProcess;


/**
* Wrapper function to run shell commands. Supports local and remote commands
Expand All @@ -88,7 +95,9 @@ public function runCommand($command){
if($this->gitEnvironment->getSsh() === true){
$fullCommand = sprintf('cd %s && %s',$this->gitPath,$command);
//$sshProcess = new SshProcess();
$this->sshProcess->run(array($fullCommand),$this->gitEnvironment->getHost(),$this->gitEnvironment->getUsername(),22,$this->gitEnvironment->getPassword());
$this->sshProcess->run(array($fullCommand),$this->gitEnvironment->getHost(),$this->gitEnvironment->getUsername()
,22,$this->gitEnvironment->getPassword(),null
,$this->gitEnvironment->getPrivateKey(),$this->gitEnvironment->getPrivateKeyPassword());
$this->logCommand($fullCommand,'remote',array('host'=>$this->gitEnvironment->getHost()),$start);

return $this->sshProcess->getStdout();
Expand Down Expand Up @@ -240,6 +249,26 @@ public function setSshProcess(SshProcessInterface $sshProcess) {
$this->sshProcess = $sshProcess;
return $this;
}

/**
* Sets the SFTP Process
* @param SshProcess $sftpProcess
* @return \VersionControl\GitCommandBundle\GitCommands\GitCommand
*/
public function setSftpProcess(SftpProcessInterface $sftpProcess) {
$this->sftpProcess = $sftpProcess;
return $this;
}

/**
* Gets the SFTP Process
*
* @return \VersionControl\GitCommandBundle\Service\SftpProcessInterface
*/
public function getSftpProcess() {
$this->sftpProcess->setGitEnviroment($this->gitEnvironment);
return $this->sftpProcess;
}

/**
* Get git command groups
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ public function getSsh();
*/
public function getHost();

/**
* Get SSH host
* @return string
*/
public function getPort();


/**
* Get SSH username
Expand All @@ -52,4 +58,16 @@ public function getUsername();
*/
public function getPassword();

/**
* Get Private Key Content
* @return string
*/
public function getPrivateKey();

/**
* Get Private Key Password
* @return string
*/
public function getPrivateKeyPassword();

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ services:
version_control.ssh_process:
class: VersionControl\GitCommandBundle\Service\SecLibSshProcess

version_control.sftp_process:
class: VersionControl\GitCommandBundle\Service\SecLibSftpProcess

version_control.git_commands:
class: VersionControl\GitCommandBundle\GitCommands\GitCommand
calls:
- [setSecurityContext, ["@security.token_storage"]]
- [setDispatcher, ["@event_dispatcher"]]
- [setLogger, ["@version_control.logger"]]
- [setSshProcess, ["@version_control.ssh_process"]]
- [setSshProcess, ["@version_control.ssh_process"]]
- [setSftpProcess, ["@version_control.sftp_process"]]

version_control.gitcommand_collector:
class: VersionControl\GitCommandBundle\Profiler\GitCommandCollector
Expand Down
156 changes: 156 additions & 0 deletions src/VersionControl/GitCommandBundle/Service/SecLibSftpProcess.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<?php

/*
* This file is part of the GitCommandBundle package.
*
* (c) Paul Schweppe <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace VersionControl\GitCommandBundle\Service;

use phpseclib\Net\SFTP;
use phpseclib\Crypt\RSA;
use VersionControl\GitCommandBundle\GitCommands\GitEnvironmentInterface;
use VersionControl\GitCommandBundle\GitCommands\Exception\SshLoginException;

/**
* Use PhpSecLib to make SFTP requests. This is a wrapper for some of the functions
* of PhpSecLib
*
* @link https://github.com/phpseclib/phpseclib
* @author Paul Schweppe <[email protected]>
*/
class SecLibSftpProcess implements SftpProcessInterface {

/**
* SFTP connection
* @var phpseclib\Net\SFTP
*/
protected $sftp = null;

/**
* The git environment with connection details
* @var VersionControl\GitCommandBundle\GitCommands\GitEnvironmentInterface
*/
protected $gitEnvironment;


public function setGitEnviroment(GitEnvironmentInterface $gitEnvironment){
if(!$gitEnvironment->getSsh()){
throw new \Exception('This Git Environment does not use SSH');
}
$this->gitEnvironment = $gitEnvironment;
}

/**
* Connects to remote server
*
* @throws \InvalidArgumentException|\RuntimeException
* @return void
*/
protected function connect()
{
$host = $this->gitEnvironment->getHost();
$username = $this->gitEnvironment->getUsername();
$port = $this->gitEnvironment->getPort();
$password = $this->gitEnvironment->getPassword();

$privateKey = $this->gitEnvironment->getPrivateKey();
$privateKeyPassword = $this->gitEnvironment->getPrivateKeyPassword();

$this->sftp = new SFTP($host, 22);

if(!$this->sftp){
throw new SshLoginException(sprintf('SSH connection failed on "%s:%s"', $host, $port));
}

if (isset($username) && $privateKey != null) {
$key = new RSA();

//Set Private Key Password
if($privateKeyPassword){
$key->setPassword($privateKeyPassword);
}
$key->loadKey($privateKey);

//Login using private key
if (!$this->sftp->login($username, $key)) {
throw new SshLoginException(sprintf('SFTP authentication failed for user "%s" using private key', $username));
}

}else{
if(!$this->sftp->login($username, $password)) {
throw new SshLoginException(sprintf('SFTP authentication failed for user "%s" using password', $username));
}
}

}

/**
* Gets the SFTP. Checks if connection already exists
* @return phpseclib\Net\SFTP
*/
protected function getSFTP(){
if(!$this->sftp){
$this->connect();
}
return $this->sftp;
}

/**
* Gets all files in a directory
* @param string $path
* @return array
*/
public function getDirectoryList($path){
return $this->getSFTP()->rawlist($path);
}

/**
* Check if file exists
* @param string $filePath
* @return boolean
*/
public function fileExists($filePath){
return $this->getSFTP()->file_exists($filePath);
}

/**
* Gets files stats
* @param string $filePath
* @return array
*/
public function getFileStats($filePath){
return $this->getSFTP()->stat($filePath);
}

/**
* Gets file contents
* @param string $filePath
* @return string
*/
public function getFileContents($filePath){
return $this->getSFTP()->get($filePath);
}

/**
* Checks if file is a directory
* @param string $filePath
* @return boolean
*/
public function isDir($filePath){
return $this->getSFTP()->is_dir($filePath);
}

/**
* Disconnect from SFTP
*/
public function disconnect(){
$this->sftp->disconnect();
$this->sftp = null;
}

}
Loading

0 comments on commit 9467766

Please sign in to comment.