Index: src/applications/drydock/interface/command/DrydockSSHCommandInterface.php =================================================================== --- src/applications/drydock/interface/command/DrydockSSHCommandInterface.php +++ src/applications/drydock/interface/command/DrydockSSHCommandInterface.php @@ -2,7 +2,34 @@ final class DrydockSSHCommandInterface extends DrydockCommandInterface { + private $keyEnvelope; + private $username; + + public function openCredentialsIfNotOpen() { + if ($this->keyEnvelope !== null) { + return; + } + + $credential = id(new PassphraseCredentialQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withIDs(array($this->getConfig('credential'))) + ->needSecrets(true) + ->executeOne(); + + if ($credential->getProvidesType() !== + PassphraseCredentialTypeSSHPrivateKey::PROVIDES_TYPE) { + throw new Exception("Only private key credentials are supported."); + } + + $this->keyEnvelope = PassphraseSSHKey::loadFromPHID( + $credential->getPHID(), + PhabricatorUser::getOmnipotentUser())->getKeyfileEnvelope(); + $this->username = $credential->getUsername(); + } + public function getExecFuture($command) { + $this->openCredentialsIfNotOpen(); + $argv = func_get_args(); // This assumes there's a UNIX shell living at the other @@ -21,32 +48,12 @@ // NOTE: The "-t -t" is for psuedo-tty allocation so we can "sudo" on some // systems, but maybe more trouble than it's worth? - - $credential = id(new PassphraseCredentialQuery()) - ->setViewer(PhabricatorUser::getOmnipotentUser()) - ->withIDs(array($this->getConfig('credential'))) - ->needSecrets(true) - ->executeOne(); - - // FIXME: We can't use text-based SSH files here because the TempFile goes - // out of scope after this function ends and thus the file gets removed - // before it can be used. - if ($credential->getCredentialType() !== - PassphraseCredentialTypeSSHPrivateKeyFile::CREDENTIAL_TYPE) { - throw new Exception("Only private key file credentials are supported."); - } - - $ssh_key = PassphraseSSHKey::loadFromPHID( - $credential->getPHID(), - PhabricatorUser::getOmnipotentUser()); - return new ExecFuture( 'ssh -t -t -o StrictHostKeyChecking=no -p %s -i %s %s@%s -- %s', $this->getConfig('port'), - $ssh_key->getKeyfileEnvelope()->openEnvelope(), - $credential->getUsername(), + $this->keyEnvelope->openEnvelope(), + $this->username, $this->getConfig('host'), $full_command); } - }