Page MenuHomePhabricator

D15755.id37974.diff
No OneTemporary

D15755.id37974.diff

diff --git a/scripts/ssh/ssh-connect.php b/scripts/ssh/ssh-connect.php
--- a/scripts/ssh/ssh-connect.php
+++ b/scripts/ssh/ssh-connect.php
@@ -34,7 +34,28 @@
$pattern[] = '-o';
$pattern[] = 'UserKnownHostsFile=/dev/null';
+$as_device = getenv('PHABRICATOR_AS_DEVICE');
$credential_phid = getenv('PHABRICATOR_CREDENTIAL');
+
+if ($as_device) {
+ $device = AlmanacKeys::getLiveDevice();
+ if (!$device) {
+ throw new Exception(
+ pht(
+ 'Attempting to create an SSH connection that authenticates with '.
+ 'the current device, but this host is not configured as a cluster '.
+ 'device.'));
+ }
+
+ if ($credential_phid) {
+ throw new Exception(
+ pht(
+ 'Attempting to proxy an SSH connection that authenticates with '.
+ 'both the current device and a specific credential. These options '.
+ 'are mutually exclusive.'));
+ }
+}
+
if ($credential_phid) {
$viewer = PhabricatorUser::getOmnipotentUser();
$key = PassphraseSSHKey::loadFromPHID($credential_phid, $viewer);
@@ -45,6 +66,13 @@
$arguments[] = $key->getKeyfileEnvelope();
}
+if ($as_device) {
+ $pattern[] = '-l %R';
+ $arguments[] = AlmanacKeys::getClusterSSHUser();
+ $pattern[] = '-i %R';
+ $arguments[] = AlmanacKeys::getKeyPath('device.key');
+}
+
$port = $args->getArg('port');
if ($port) {
$pattern[] = '-p %d';
diff --git a/scripts/ssh/ssh-exec.php b/scripts/ssh/ssh-exec.php
--- a/scripts/ssh/ssh-exec.php
+++ b/scripts/ssh/ssh-exec.php
@@ -153,32 +153,37 @@
->splitArguments($original_command);
if ($device) {
- $act_as_name = array_shift($original_argv);
- if (!preg_match('/^@/', $act_as_name)) {
- throw new Exception(
- pht(
- 'Commands executed by devices must identify an acting user in the '.
- 'first command argument. This request was not constructed '.
- 'properly.'));
+ // If we're authenticating as a device, the first argument may be a
+ // "@username" argument to act as a particular user.
+ $first_argument = head($original_argv);
+ if (preg_match('/^@/', $first_argument)) {
+ $act_as_name = array_shift($original_argv);
+ $act_as_name = substr($act_as_name, 1);
+ $user = id(new PhabricatorPeopleQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withUsernames(array($act_as_name))
+ ->executeOne();
+ if (!$user) {
+ throw new Exception(
+ pht(
+ 'Device request identifies an acting user with an invalid '.
+ 'username ("%s"). There is no user with this username.',
+ $act_as_name));
+ }
+ } else {
+ $user = PhabricatorUser::getOmnipotentUser();
}
+ }
- $act_as_name = substr($act_as_name, 1);
- $user = id(new PhabricatorPeopleQuery())
- ->setViewer(PhabricatorUser::getOmnipotentUser())
- ->withUsernames(array($act_as_name))
- ->executeOne();
- if (!$user) {
- throw new Exception(
- pht(
- 'Device request identifies an acting user with an invalid '.
- 'username ("%s"). There is no user with this username.',
- $act_as_name));
- }
+ if ($user->isOmnipotent()) {
+ $user_name = 'device/'.$device->getName();
+ } else {
+ $user_name = $user->getUsername();
}
$ssh_log->setData(
array(
- 'u' => $user->getUsername(),
+ 'u' => $user_name,
'P' => $user->getPHID(),
));
@@ -187,7 +192,7 @@
pht(
'Your account ("%s") does not have permission to establish SSH '.
'sessions. Visit the web interface for more information.',
- $user->getUsername()));
+ $user_name));
}
$workflows = id(new PhutilClassMapQuery())
@@ -206,7 +211,7 @@
"Usually, you should run a command like `%s` or `%s` ".
"rather than connecting directly with SSH.\n\n".
"Supported commands are: %s.",
- $user->getUsername(),
+ $user_name,
'git clone',
'hg push',
implode(', ', array_keys($workflows))));
diff --git a/src/applications/diffusion/protocol/DiffusionCommandEngine.php b/src/applications/diffusion/protocol/DiffusionCommandEngine.php
--- a/src/applications/diffusion/protocol/DiffusionCommandEngine.php
+++ b/src/applications/diffusion/protocol/DiffusionCommandEngine.php
@@ -7,6 +7,7 @@
private $credentialPHID;
private $argv;
private $passthru;
+ private $connectAsDevice;
public static function newCommandEngine(PhabricatorRepository $repository) {
$engines = self::newCommandEngines();
@@ -82,6 +83,15 @@
return $this->passthru;
}
+ public function setConnectAsDevice($connect_as_device) {
+ $this->connectAsDevice = $connect_as_device;
+ return $this;
+ }
+
+ public function getConnectAsDevice() {
+ return $this->connectAsDevice;
+ }
+
public function newFuture() {
$argv = $this->newCommandArgv();
$env = $this->newCommandEnvironment();
@@ -118,6 +128,8 @@
}
private function newCommonEnvironment() {
+ $repository = $this->getRepository();
+
$env = array();
// NOTE: Force the language to "en_US.UTF-8", which overrides locale
// settings. This makes stuff print in English instead of, e.g., French,
@@ -127,11 +139,43 @@
// Propagate PHABRICATOR_ENV explicitly. For discussion, see T4155.
$env['PHABRICATOR_ENV'] = PhabricatorEnv::getSelectedEnvironmentName();
+ $as_device = $this->getConnectAsDevice();
+ $credential_phid = $this->getCredentialPHID();
+
+ if ($as_device) {
+ $device = AlmanacKeys::getLiveDevice();
+ if (!$device) {
+ throw new Exception(
+ pht(
+ 'Attempting to build a reposiory command (for repository "%s") '.
+ 'as device, but this host ("%s") is not configured as a cluster '.
+ 'device.',
+ $repository->getDisplayName(),
+ php_uname('n')));
+ }
+
+ if ($credential_phid) {
+ throw new Exception(
+ pht(
+ 'Attempting to build a repository command (for repository "%s"), '.
+ 'but the CommandEngine is configured to connect as both the '.
+ 'current cluster device ("%s") and with a specific credential '.
+ '("%s"). These options are mutually exclusive. Connections must '.
+ 'authenticate as one or the other, not both.',
+ $repository->getDisplayName(),
+ $device->getName(),
+ $credential_phid));
+ }
+ }
+
+
if ($this->isAnySSHProtocol()) {
- $credential_phid = $this->getCredentialPHID();
if ($credential_phid) {
$env['PHABRICATOR_CREDENTIAL'] = $credential_phid;
}
+ if ($as_device) {
+ $env['PHABRICATOR_AS_DEVICE'] = 1;
+ }
}
return $env;

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 21, 6:38 PM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7688933
Default Alt Text
D15755.id37974.diff (6 KB)

Event Timeline