1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-05 03:18:25 +01:00

Add keyfile and HTTP Basic auth support to repositories

Summary: I still need to go through all the daemon and Diffusion code and change
the bare execx() calls to $repository->execxXXX() to actually make this work,
but we're getting close.

Test Plan: Configured repositories with various HTTP / SVN setups and ran the
test_connection.php script to verify keys were located and added and
username/password information was supplied.

Reviewers: jungejason, nh, tuomaspelkonen, aran

Reviewed By: nh

CC: aran, nh, jungejason

Differential Revision: 902
This commit is contained in:
epriestley 2011-09-06 09:37:35 -07:00
parent 40c1450129
commit e3a9d73fe1
4 changed files with 131 additions and 19 deletions

View file

@ -205,6 +205,9 @@ class PhabricatorRepositoryEditController
$is_git = false;
$is_svn = false;
$e_ssh_key = null;
$e_ssh_keyfile = null;
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$is_git = true;
@ -241,6 +244,19 @@ class PhabricatorRepositoryEditController
$repository->setDetail('ssh-login', $request->getStr('ssh-login'));
$repository->setDetail('ssh-key', $request->getStr('ssh-key'));
$repository->setDetail('ssh-keyfile', $request->getStr('ssh-keyfile'));
$repository->setDetail('http-login', $request->getStr('http-login'));
$repository->setDetail('http-pass', $request->getStr('http-pass'));
if ($repository->getDetail('ssh-key') &&
$repository->getDetail('ssh-keyfile')) {
$errors[] =
"Specify only one of 'SSH Private Key' and 'SSH Private Key File', ".
"not both.";
$e_ssh_key = 'Choose Only One';
$e_ssh_keyfile = 'Choose Only One';
}
$repository->setDetail(
'herald-disabled',
@ -392,8 +408,8 @@ class PhabricatorRepositoryEditController
'<div class="aphront-form-instructions">'.
'If you want to connect to this repository over SSH, enter the '.
'username and private key to use. You can leave these fields blank if '.
'the repository does not use SSH. <strong>NOTE: This feature is not '.
'yet fully supported.</strong>'.
'the repository does not use SSH.'.
' <strong>NOTE: This feature is not yet fully supported.</strong>'.
'</div>');
$form
@ -407,14 +423,55 @@ class PhabricatorRepositoryEditController
->setName('ssh-key')
->setLabel('SSH Private Key')
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
->setValue($repository->getDetail('ssh-key')))
->setValue($repository->getDetail('ssh-key'))
->setError($e_ssh_key)
->setCaption('Specify the entire private key, <em>or</em>...'))
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel('Test Connection')
->setValue(
'To test these credentials, <strong>save this form</strong> and '.
'then run: <code>phabricator/scripts/repository/test_connection'.
'.php '.phutil_escape_html($repository->getCallsign()).'</code>'));
id(new AphrontFormTextControl())
->setName('ssh-keyfile')
->setLabel('SSH Private Key File')
->setValue($repository->getDetail('ssh-keyfile'))
->setError($e_ssh_keyfile)
->setCaption(
'...specify a path on disk where the daemon should '.
'look for a private key.'));
$supports_http = $is_svn;
if ($supports_http) {
$form
->appendChild(
'<div class="aphront-form-instructions">'.
'If you want to connect to this repository over HTTP Basic Auth, '.
'enter the username and password to use. You can leave these '.
'fields blank if the repository does not use HTTP Basic Auth.'.
' <strong>NOTE: This feature is not yet fully supported.</strong>'.
'</div>')
->appendChild(
id(new AphrontFormTextControl())
->setName('http-login')
->setLabel('HTTP Basic Login')
->setValue($repository->getDetail('http-login')))
->appendChild(
id(new AphrontFormTextControl())
->setName('http-pass')
->setLabel('HTTP Basic Password')
->setValue($repository->getDetail('http-pass')));
}
$form
->appendChild(
'<div class="aphront-form-important">'.
'To test your authentication configuration, <strong>save this '.
'form</strong> and then run this script:'.
'<code>'.
'phabricator/ $ ./scripts/repository/test_connection.php '.
phutil_escape_html($repository->getCallsign()).
'</code>'.
'This will verify that your configuration is correct and the '.
'daemons can connect to the remote repository and pull changes '.
'from it.'.
'</div>');
$form->appendChild('</div>');

View file

@ -17,7 +17,6 @@ phutil_require_module('phabricator', 'applications/repository/storage/repository
phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/markup');
phutil_require_module('phabricator', 'view/form/control/select');
phutil_require_module('phabricator', 'view/form/control/static');
phutil_require_module('phabricator', 'view/form/control/submit');

View file

@ -128,7 +128,7 @@ class PhabricatorRepository extends PhabricatorRepositoryDAO {
if ($this->shouldUseSSH()) {
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$pattern = "SVN_SSH=%s svn {$pattern}";
$pattern = "SVN_SSH=%s svn --non-interactive {$pattern}";
array_unshift(
$args,
csprintf(
@ -160,10 +160,30 @@ class PhabricatorRepository extends PhabricatorRepositoryDAO {
default:
throw new Exception("Unrecognized version control system.");
}
} else if ($this->shouldUseHTTP()) {
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$pattern =
"svn ".
"--non-interactive ".
"--no-auth-cache ".
"--trust-server-cert ".
"--username %s ".
"--password %s ".
$pattern;
array_unshift(
$args,
$this->getDetail('http-login'),
$this->getDetail('http-pass'));
break;
default:
throw new Exception(
"No support for HTTP Basic Auth in this version control system.");
}
} else {
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$pattern = "svn {$pattern}";
$pattern = "svn --non-interactive {$pattern}";
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$pattern = "git {$pattern}";
@ -187,7 +207,7 @@ class PhabricatorRepository extends PhabricatorRepositoryDAO {
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$pattern = "(cd %s && svn {$pattern})";
$pattern = "(cd %s && svn --non-interactive {$pattern})";
array_unshift($args, $this->getLocalPath());
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
@ -212,11 +232,21 @@ class PhabricatorRepository extends PhabricatorRepositoryDAO {
}
private function getSSHKeyfile() {
if (!$this->sshKeyfile) {
$keyfile = new TempFile('phabricator-repository-ssh-key');
chmod($keyfile, 0600);
Filesystem::writeFile($keyfile, $this->getDetail('ssh-key'));
$this->sshKeyfile = $keyfile;
if ($this->sshKeyfile === null) {
$key = $this->getDetail('ssh-key');
$keyfile = $this->getDetail('ssh-keyfile');
if ($keyfile) {
// Make sure we can read the file, that it exists, etc.
Filesystem::readFile($keyfile);
$this->sshKeyfile = $keyfile;
} else if ($key) {
$keyfile = new TempFile('phabricator-repository-ssh-key');
chmod($keyfile, 0600);
Filesystem::writeFile($keyfile, $key);
$this->sshKeyfile = $keyfile;
} else {
$this->sshKeyfile = '';
}
}
return (string)$this->sshKeyfile;
@ -226,7 +256,17 @@ class PhabricatorRepository extends PhabricatorRepositoryDAO {
$uri = new PhutilURI($this->getRemoteURI());
$protocol = $uri->getProtocol();
if ($this->isSSHProtocol($protocol)) {
return (bool)$this->getDetail('ssh-key');
return (bool)$this->getSSHKeyfile();
} else {
return false;
}
}
public function shouldUseHTTP() {
$uri = new PhutilURI($this->getRemoteURI());
$protocol = $uri->getProtocol();
if ($this->isHTTPProtocol($protocol)) {
return (bool)$this->getDetail('http-login');
} else {
return false;
}
@ -236,4 +276,8 @@ class PhabricatorRepository extends PhabricatorRepositoryDAO {
return ($protocol == 'ssh' || $protocol == 'svn+ssh');
}
private function isHTTPProtocol($protocol) {
return ($protocol == 'http' || $protocol == 'https');
}
}

View file

@ -87,6 +87,18 @@
margin: 0.75em 3% 1.25em;
}
.aphront-form-important {
margin: .5em 0;
background: #ffffdd;
padding: .5em 1em;
}
.aphront-form-important code {
display: block;
padding: .25em;
margin: .5em 2em;
}
.aphront-form-control-static .aphront-form-input {
padding-top: 4px;
font-size: 13px;