Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15417795
D15755.id37974.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D15755.id37974.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D15755: Allow cluster devices to SSH to one another without acting as a user
Attached
Detach File
Event Timeline
Log In to Comment