1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-29 02:02:41 +01:00

Generate a random unique "Request ID" for SSH requests so processes can coordinate better

Summary:
Depends on D19247. Ref T13109. When we receive an SSH request, generate a random unique ID for the request. Then thread it down through the process tree.

The immediate goal is to let the `ssh-exec` process coordinate with `commit-hook` process and log information about read and write lock wait times. Today, there's no way for `ssh-exec` to interact with the `PushEvent`, but this is the most helpful place to store this data for users.

Test Plan: Made pushes, saw the `PushEvent` table populate with a random request ID. Exported data and saw the ID preserved in the export.

Maniphest Tasks: T13109

Differential Revision: https://secure.phabricator.com/D19249
This commit is contained in:
epriestley 2018-03-22 12:42:08 -07:00
parent e010aaca43
commit 69bff489d4
9 changed files with 69 additions and 3 deletions

View file

@ -0,0 +1,5 @@
ALTER TABLE {$NAMESPACE}_repository.repository_pushevent
ADD requestIdentifier VARBINARY(12);
ALTER TABLE {$NAMESPACE}_repository.repository_pushevent
ADD UNIQUE KEY `key_request` (requestIdentifier);

View file

@ -187,6 +187,11 @@ if (strlen($remote_protocol)) {
$engine->setRemoteProtocol($remote_protocol); $engine->setRemoteProtocol($remote_protocol);
} }
$request_identifier = getenv(DiffusionCommitHookEngine::ENV_REQUEST);
if (strlen($request_identifier)) {
$engine->setRequestIdentifier($request_identifier);
}
try { try {
$err = $engine->execute(); $err = $engine->execute();
} catch (DiffusionCommitHookRejectException $ex) { } catch (DiffusionCommitHookRejectException $ex) {

View file

@ -8,6 +8,12 @@ require_once $root.'/scripts/__init_script__.php';
$ssh_log = PhabricatorSSHLog::getLog(); $ssh_log = PhabricatorSSHLog::getLog();
$request_identifier = Filesystem::readRandomCharacters(12);
$ssh_log->setData(
array(
'Q' => $request_identifier,
));
$args = new PhutilArgumentParser($argv); $args = new PhutilArgumentParser($argv);
$args->setTagline(pht('execute SSH requests')); $args->setTagline(pht('execute SSH requests'));
$args->setSynopsis(<<<EOSYNOPSIS $args->setSynopsis(<<<EOSYNOPSIS
@ -248,6 +254,7 @@ try {
$workflow->setSSHUser($user); $workflow->setSSHUser($user);
$workflow->setOriginalArguments($original_argv); $workflow->setOriginalArguments($original_argv);
$workflow->setIsClusterRequest($is_cluster_request); $workflow->setIsClusterRequest($is_cluster_request);
$workflow->setRequestIdentifier($request_identifier);
$sock_stdin = fopen('php://stdin', 'r'); $sock_stdin = fopen('php://stdin', 'r');
if (!$sock_stdin) { if (!$sock_stdin) {

View file

@ -47,6 +47,10 @@ final class PhabricatorAccessLogConfigOptions
's' => pht('The system user.'), 's' => pht('The system user.'),
'S' => pht('The system sudo user.'), 'S' => pht('The system sudo user.'),
'k' => pht('ID of the SSH key used to authenticate the request.'), 'k' => pht('ID of the SSH key used to authenticate the request.'),
// TODO: This is a reasonable thing to support in the HTTP access
// log, too.
'Q' => pht('A random, unique string which identifies the request.'),
); );
$http_desc = pht( $http_desc = pht(

View file

@ -12,6 +12,7 @@ final class DiffusionCommitHookEngine extends Phobject {
const ENV_REPOSITORY = 'PHABRICATOR_REPOSITORY'; const ENV_REPOSITORY = 'PHABRICATOR_REPOSITORY';
const ENV_USER = 'PHABRICATOR_USER'; const ENV_USER = 'PHABRICATOR_USER';
const ENV_REQUEST = 'PHABRICATOR_REQUEST';
const ENV_REMOTE_ADDRESS = 'PHABRICATOR_REMOTE_ADDRESS'; const ENV_REMOTE_ADDRESS = 'PHABRICATOR_REMOTE_ADDRESS';
const ENV_REMOTE_PROTOCOL = 'PHABRICATOR_REMOTE_PROTOCOL'; const ENV_REMOTE_PROTOCOL = 'PHABRICATOR_REMOTE_PROTOCOL';
@ -25,6 +26,7 @@ final class DiffusionCommitHookEngine extends Phobject {
private $subversionRepository; private $subversionRepository;
private $remoteAddress; private $remoteAddress;
private $remoteProtocol; private $remoteProtocol;
private $requestIdentifier;
private $transactionKey; private $transactionKey;
private $mercurialHook; private $mercurialHook;
private $mercurialCommits = array(); private $mercurialCommits = array();
@ -58,6 +60,15 @@ final class DiffusionCommitHookEngine extends Phobject {
return $this->remoteAddress; return $this->remoteAddress;
} }
public function setRequestIdentifier($request_identifier) {
$this->requestIdentifier = $request_identifier;
return $this;
}
public function getRequestIdentifier() {
return $this->requestIdentifier;
}
public function setSubversionTransactionInfo($transaction, $repository) { public function setSubversionTransactionInfo($transaction, $repository) {
$this->subversionTransaction = $transaction; $this->subversionTransaction = $transaction;
$this->subversionRepository = $repository; $this->subversionRepository = $repository;
@ -620,6 +631,7 @@ final class DiffusionCommitHookEngine extends Phobject {
$env = array( $env = array(
self::ENV_REPOSITORY => $this->getRepository()->getPHID(), self::ENV_REPOSITORY => $this->getRepository()->getPHID(),
self::ENV_USER => $this->getViewer()->getUsername(), self::ENV_USER => $this->getViewer()->getUsername(),
self::ENV_REQUEST => $this->getRequestIdentifier(),
self::ENV_REMOTE_PROTOCOL => $this->getRemoteProtocol(), self::ENV_REMOTE_PROTOCOL => $this->getRemoteProtocol(),
self::ENV_REMOTE_ADDRESS => $this->getRemoteAddress(), self::ENV_REMOTE_ADDRESS => $this->getRemoteAddress(),
); );
@ -1081,16 +1093,24 @@ final class DiffusionCommitHookEngine extends Phobject {
->setDevicePHID($device_phid) ->setDevicePHID($device_phid)
->setRepositoryPHID($this->getRepository()->getPHID()) ->setRepositoryPHID($this->getRepository()->getPHID())
->attachRepository($this->getRepository()) ->attachRepository($this->getRepository())
->setEpoch(time()); ->setEpoch(PhabricatorTime::getNow());
} }
private function newPushEvent() { private function newPushEvent() {
$viewer = $this->getViewer(); $viewer = $this->getViewer();
return PhabricatorRepositoryPushEvent::initializeNewEvent($viewer)
$event = PhabricatorRepositoryPushEvent::initializeNewEvent($viewer)
->setRepositoryPHID($this->getRepository()->getPHID()) ->setRepositoryPHID($this->getRepository()->getPHID())
->setRemoteAddress($this->getRemoteAddress()) ->setRemoteAddress($this->getRemoteAddress())
->setRemoteProtocol($this->getRemoteProtocol()) ->setRemoteProtocol($this->getRemoteProtocol())
->setEpoch(time()); ->setEpoch(PhabricatorTime::getNow());
$identifier = $this->getRequestIdentifier();
if (strlen($identifier)) {
$event->setRequestIdentifier($identifier);
}
return $event;
} }
private function rejectEnormousChanges(array $content_updates) { private function rejectEnormousChanges(array $content_updates) {

View file

@ -30,6 +30,11 @@ abstract class DiffusionSSHWorkflow extends PhabricatorSSHWorkflow {
DiffusionCommitHookEngine::ENV_REMOTE_PROTOCOL => 'ssh', DiffusionCommitHookEngine::ENV_REMOTE_PROTOCOL => 'ssh',
); );
$identifier = $this->getRequestIdentifier();
if ($identifier !== null) {
$env[DiffusionCommitHookEngine::ENV_REQUEST] = $identifier;
}
$remote_address = $this->getSSHRemoteAddress(); $remote_address = $this->getSSHRemoteAddress();
if ($remote_address !== null) { if ($remote_address !== null) {
$env[DiffusionCommitHookEngine::ENV_REMOTE_ADDRESS] = $remote_address; $env[DiffusionCommitHookEngine::ENV_REMOTE_ADDRESS] = $remote_address;

View file

@ -101,6 +101,9 @@ final class PhabricatorRepositoryPushLogSearchEngine
$fields[] = id(new PhabricatorIDExportField()) $fields[] = id(new PhabricatorIDExportField())
->setKey('pushID') ->setKey('pushID')
->setLabel(pht('Push ID')), ->setLabel(pht('Push ID')),
$fields[] = id(new PhabricatorStringExportField())
->setKey('unique')
->setLabel(pht('Unique')),
$fields[] = id(new PhabricatorStringExportField()) $fields[] = id(new PhabricatorStringExportField())
->setKey('protocol') ->setKey('protocol')
->setLabel(pht('Protocol')), ->setLabel(pht('Protocol')),
@ -209,6 +212,7 @@ final class PhabricatorRepositoryPushLogSearchEngine
$map = array( $map = array(
'pushID' => $event->getID(), 'pushID' => $event->getID(),
'unique' => $event->getRequestIdentifier(),
'protocol' => $event->getRemoteProtocol(), 'protocol' => $event->getRemoteProtocol(),
'repositoryPHID' => $repository_phid, 'repositoryPHID' => $repository_phid,
'repository' => $repository_name, 'repository' => $repository_name,

View file

@ -11,6 +11,7 @@ final class PhabricatorRepositoryPushEvent
protected $repositoryPHID; protected $repositoryPHID;
protected $epoch; protected $epoch;
protected $pusherPHID; protected $pusherPHID;
protected $requestIdentifier;
protected $remoteAddress; protected $remoteAddress;
protected $remoteProtocol; protected $remoteProtocol;
protected $rejectCode; protected $rejectCode;
@ -29,6 +30,7 @@ final class PhabricatorRepositoryPushEvent
self::CONFIG_AUX_PHID => true, self::CONFIG_AUX_PHID => true,
self::CONFIG_TIMESTAMPS => false, self::CONFIG_TIMESTAMPS => false,
self::CONFIG_COLUMN_SCHEMA => array( self::CONFIG_COLUMN_SCHEMA => array(
'requestIdentifier' => 'bytes12?',
'remoteAddress' => 'ipaddress?', 'remoteAddress' => 'ipaddress?',
'remoteProtocol' => 'text32?', 'remoteProtocol' => 'text32?',
'rejectCode' => 'uint32', 'rejectCode' => 'uint32',
@ -38,6 +40,10 @@ final class PhabricatorRepositoryPushEvent
'key_repository' => array( 'key_repository' => array(
'columns' => array('repositoryPHID'), 'columns' => array('repositoryPHID'),
), ),
'key_request' => array(
'columns' => array('requestIdentifier'),
'unique' => true,
),
), ),
) + parent::getConfiguration(); ) + parent::getConfiguration();
} }

View file

@ -13,6 +13,7 @@ abstract class PhabricatorSSHWorkflow
private $errorChannel; private $errorChannel;
private $isClusterRequest; private $isClusterRequest;
private $originalArguments; private $originalArguments;
private $requestIdentifier;
public function isExecutable() { public function isExecutable() {
return false; return false;
@ -89,6 +90,15 @@ abstract class PhabricatorSSHWorkflow
return $this->originalArguments; return $this->originalArguments;
} }
public function setRequestIdentifier($request_identifier) {
$this->requestIdentifier = $request_identifier;
return $this;
}
public function getRequestIdentifier() {
return $this->requestIdentifier;
}
public function getSSHRemoteAddress() { public function getSSHRemoteAddress() {
$ssh_client = getenv('SSH_CLIENT'); $ssh_client = getenv('SSH_CLIENT');
if (!strlen($ssh_client)) { if (!strlen($ssh_client)) {