mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 08:42:41 +01:00
Route internal conduit calls if other hosts available
Summary: Ref T2785 Looks for hosts in `conduit.servers` config and if any exist route any conduit calls through any one of the hosts. Test Plan: Make some curl calls to public methods (`conduit.ping`), watch the access log for two requests. Make some calls from the UI that require authentication, watch the access log a bit more. Also ran the unit tests. Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Maniphest Tasks: T2785 Differential Revision: https://secure.phabricator.com/D5970
This commit is contained in:
parent
a1a46656cb
commit
94e7878a57
7 changed files with 118 additions and 14 deletions
|
@ -830,6 +830,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorChatLogQuery' => 'applications/chatlog/PhabricatorChatLogQuery.php',
|
||||
'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php',
|
||||
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php',
|
||||
'PhabricatorConduitConfigOptions' => 'applications/conduit/config/PhabricatorConduitConfigOptions.php',
|
||||
'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/PhabricatorConduitConnectionLog.php',
|
||||
'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php',
|
||||
'PhabricatorConduitController' => 'applications/conduit/controller/PhabricatorConduitController.php',
|
||||
|
@ -2601,6 +2602,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
|
||||
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
|
||||
'PhabricatorConduitConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
|
||||
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
|
||||
'PhabricatorConduitController' => 'PhabricatorController',
|
||||
|
|
|
@ -117,14 +117,29 @@ abstract class AphrontApplicationConfiguration {
|
|||
$host = $request->getHost();
|
||||
$base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri');
|
||||
$prod_uri = PhabricatorEnv::getEnvConfig('phabricator.production-uri');
|
||||
$file_uri = PhabricatorEnv::getEnvConfig('security.alternate-file-domain');
|
||||
$file_uri = PhabricatorEnv::getEnvConfig(
|
||||
'security.alternate-file-domain');
|
||||
$conduit_uris = PhabricatorEnv::getEnvConfig('conduit.servers');
|
||||
|
||||
$uris = array_merge(
|
||||
array(
|
||||
$base_uri,
|
||||
$prod_uri,
|
||||
$file_uri,
|
||||
),
|
||||
$conduit_uris);
|
||||
|
||||
$host_match = false;
|
||||
foreach ($uris as $uri) {
|
||||
if ($host === id(new PhutilURI($uri))->getDomain()) {
|
||||
$host_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: If the base URI isn't defined yet, don't activate alternate
|
||||
// domains.
|
||||
if ($base_uri &&
|
||||
$host != id(new PhutilURI($base_uri))->getDomain() &&
|
||||
$host != id(new PhutilURI($prod_uri))->getDomain() &&
|
||||
$host != id(new PhutilURI($file_uri))->getDomain()) {
|
||||
if ($base_uri && !$host_match) {
|
||||
|
||||
try {
|
||||
$blog = id(new PhameBlogQuery())
|
||||
|
|
|
@ -13,10 +13,14 @@ final class ConduitCall {
|
|||
private $method;
|
||||
private $request;
|
||||
private $user;
|
||||
private $servers;
|
||||
private $forceLocal;
|
||||
|
||||
public function __construct($method, array $params) {
|
||||
$this->method = $method;
|
||||
$this->handler = $this->buildMethodHandler($method);
|
||||
$this->servers = PhabricatorEnv::getEnvConfig('conduit.servers');
|
||||
$this->forceLocal = false;
|
||||
|
||||
$invalid_params = array_diff_key(
|
||||
$params,
|
||||
|
@ -27,6 +31,16 @@ final class ConduitCall {
|
|||
implode("', '", array_keys($invalid_params)) . "'.");
|
||||
}
|
||||
|
||||
if ($this->servers) {
|
||||
$current_host = AphrontRequest::getHTTPHeader('HOST');
|
||||
foreach ($this->servers as $server) {
|
||||
if ($current_host === id(new PhutilURI($server))->getDomain()) {
|
||||
$this->forceLocal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->request = new ConduitAPIRequest($params);
|
||||
}
|
||||
|
||||
|
@ -39,6 +53,15 @@ final class ConduitCall {
|
|||
return $this->user;
|
||||
}
|
||||
|
||||
public function setForceLocal($force_local) {
|
||||
$this->forceLocal = $force_local;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function shouldForceLocal() {
|
||||
return $this->forceLocal;
|
||||
}
|
||||
|
||||
public function shouldRequireAuthentication() {
|
||||
return $this->handler->shouldRequireAuthentication();
|
||||
}
|
||||
|
@ -64,8 +87,36 @@ final class ConduitCall {
|
|||
$this->request->setUser($this->getUser());
|
||||
}
|
||||
|
||||
if (!$this->shouldForceLocal() && $this->servers) {
|
||||
$server = $this->pickRandomServer($this->servers);
|
||||
$client = new ConduitClient($server);
|
||||
$params = $this->request->getAllParameters();
|
||||
|
||||
$params["__conduit__"]["isProxied"] = true;
|
||||
|
||||
if ($this->handler->shouldRequireAuthentication()) {
|
||||
$client->callMethodSynchronous(
|
||||
'conduit.connect',
|
||||
array(
|
||||
'client' => 'PhabricatorConduit',
|
||||
'clientVersion' => '1.0',
|
||||
'user' => $this->getUser()->getUserName(),
|
||||
'certificate' => $this->getUser()->getConduitCertificate(),
|
||||
'__conduit__' => $params["__conduit__"],
|
||||
));
|
||||
}
|
||||
|
||||
return $client->callMethodSynchronous(
|
||||
$this->method,
|
||||
$params);
|
||||
} else {
|
||||
return $this->handler->executeMethod($this->request);
|
||||
}
|
||||
}
|
||||
|
||||
protected function pickRandomServer($servers) {
|
||||
return $servers[array_rand($servers)];
|
||||
}
|
||||
|
||||
protected function buildMethodHandler($method) {
|
||||
$method_class = ConduitAPIMethod::getClassNameFromAPIMethodName($method);
|
||||
|
|
|
@ -4,13 +4,15 @@ final class ConduitCallTestCase extends PhabricatorTestCase {
|
|||
|
||||
public function testConduitPing() {
|
||||
$call = new ConduitCall('conduit.ping', array());
|
||||
$call->setForceLocal(true);
|
||||
$result = $call->execute();
|
||||
|
||||
$this->assertEqual(false, empty($result));
|
||||
}
|
||||
|
||||
public function testConduitAuth() {
|
||||
$call = new ConduitCall('user.whoami', array());
|
||||
$call = new ConduitCall('user.whoami', array(), true);
|
||||
$call->setForceLocal(true);
|
||||
|
||||
$caught = null;
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorConduitConfigOptions
|
||||
extends PhabricatorApplicationConfigOptions {
|
||||
|
||||
public function getName() {
|
||||
return pht("Conduit");
|
||||
}
|
||||
|
||||
public function getDescription() {
|
||||
return pht("Configure conduit.");
|
||||
}
|
||||
|
||||
public function getOptions() {
|
||||
return array(
|
||||
$this->newOption("conduit.servers", "list<string>", array())
|
||||
->setLocked(true)
|
||||
->setSummary(pht("Servers that conduit can connect to."))
|
||||
->setDescription(
|
||||
pht(
|
||||
"Set an array of servers where conduit can connect to. This is ".
|
||||
"an advanced option. Don't touch this unless you know what you ".
|
||||
"are doing."))
|
||||
->addExample(
|
||||
'["http://phabricator2.example.com/", '.
|
||||
'"http://phabricator3.example.com/]"',
|
||||
pht('Valid Setting')),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -35,7 +35,8 @@ final class PhabricatorConduitAPIController
|
|||
$metadata = idx($params, '__conduit__', array());
|
||||
unset($params['__conduit__']);
|
||||
|
||||
$call = new ConduitCall($method, $params);
|
||||
$call = new ConduitCall(
|
||||
$method, $params, idx($metadata, 'isProxied', false));
|
||||
|
||||
$result = null;
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ final class ConduitAPI_differential_finishpostponedlinters_Method
|
|||
'diff_id' => $diff_id,
|
||||
'name' => 'arc:lint',
|
||||
'data' => json_encode($messages)));
|
||||
$call->setForceLocal(true);
|
||||
$call->setUser($request->getUser());
|
||||
$call->execute();
|
||||
$call = new ConduitCall(
|
||||
|
@ -106,6 +107,7 @@ final class ConduitAPI_differential_finishpostponedlinters_Method
|
|||
'diff_id' => $diff_id,
|
||||
'name' => 'arc:lint-postponed',
|
||||
'data' => json_encode($postponed_linters)));
|
||||
$call->setForceLocal(true);
|
||||
$call->setUser($request->getUser());
|
||||
$call->execute();
|
||||
|
||||
|
|
Loading…
Reference in a new issue