Page MenuHomePhabricator

D10495.diff
No OneTemporary

D10495.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -880,10 +880,12 @@
'DrydockResourceViewController' => 'applications/drydock/controller/DrydockResourceViewController.php',
'DrydockSFTPFilesystemInterface' => 'applications/drydock/interface/filesystem/DrydockSFTPFilesystemInterface.php',
'DrydockSSHCommandInterface' => 'applications/drydock/interface/command/DrydockSSHCommandInterface.php',
+ 'DrydockSetupCheckWinRM' => 'applications/drydock/check/DrydockSetupCheckWinRM.php',
'DrydockSlotLock' => 'applications/drydock/storage/DrydockSlotLock.php',
'DrydockSlotLockException' => 'applications/drydock/exception/DrydockSlotLockException.php',
'DrydockSlotLockFailureLogType' => 'applications/drydock/logtype/DrydockSlotLockFailureLogType.php',
'DrydockWebrootInterface' => 'applications/drydock/interface/webroot/DrydockWebrootInterface.php',
+ 'DrydockWinRMCommandInterface' => 'applications/drydock/interface/command/DrydockWinRMCommandInterface.php',
'DrydockWorker' => 'applications/drydock/worker/DrydockWorker.php',
'DrydockWorkingCopyBlueprintImplementation' => 'applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php',
'FeedConduitAPIMethod' => 'applications/feed/conduit/FeedConduitAPIMethod.php',
@@ -4633,10 +4635,12 @@
'DrydockResourceViewController' => 'DrydockResourceController',
'DrydockSFTPFilesystemInterface' => 'DrydockFilesystemInterface',
'DrydockSSHCommandInterface' => 'DrydockCommandInterface',
+ 'DrydockSetupCheckWinRM' => 'PhabricatorSetupCheck',
'DrydockSlotLock' => 'DrydockDAO',
'DrydockSlotLockException' => 'Exception',
'DrydockSlotLockFailureLogType' => 'DrydockLogType',
'DrydockWebrootInterface' => 'DrydockInterface',
+ 'DrydockWinRMCommandInterface' => 'DrydockCommandInterface',
'DrydockWorker' => 'PhabricatorWorker',
'DrydockWorkingCopyBlueprintImplementation' => 'DrydockBlueprintImplementation',
'FeedConduitAPIMethod' => 'ConduitAPIMethod',
diff --git a/src/applications/drydock/check/DrydockSetupCheckWinRM.php b/src/applications/drydock/check/DrydockSetupCheckWinRM.php
new file mode 100644
--- /dev/null
+++ b/src/applications/drydock/check/DrydockSetupCheckWinRM.php
@@ -0,0 +1,41 @@
+<?php
+
+final class DrydockSetupCheckWinRM extends PhabricatorSetupCheck {
+
+ protected function executeChecks() {
+
+ $drydock_app = 'PhabricatorDrydockApplication';
+ if (!PhabricatorApplication::isClassInstalled($drydock_app)) {
+ return;
+ }
+
+ if (!Filesystem::binaryExists('winrm')) {
+ $preamble = pht(
+ "The 'winrm' binary could not be found. This utility is used to ".
+ "run commands on remote Windows machines when they are leased through ".
+ "Drydock.\n\n".
+ "You will most likely need to download and compile it from ".
+ "%s, using the Go compiler. Once you have, place the binary ".
+ "somewhere in your %s.",
+ phutil_tag(
+ 'a',
+ array('href' => 'https://github.com/masterzen/winrm'),
+ 'https://github.com/masterzen/winrm'),
+ phutil_tag('tt', array(), 'PATH'));
+
+ $message = pht(
+ 'You only need this binary if you are leasing Windows hosts in '.
+ 'Drydock or Harbormaster. If you don\'t need to run commands on '.
+ 'Windows machines, you can safely ignore this message.');
+
+ $this->newIssue('bin.winrm')
+ ->setShortName(pht("'%s' Missing", 'winrm'))
+ ->setName(pht("Missing '%s' Binary", 'winrm'))
+ ->setSummary(
+ pht("The '%s' binary could not be located or executed.", 'winrm'))
+ ->setMessage(pht("%s\n\n%s", $preamble, $message));
+ }
+
+ }
+
+}
diff --git a/src/applications/drydock/interface/command/DrydockWinRMCommandInterface.php b/src/applications/drydock/interface/command/DrydockWinRMCommandInterface.php
new file mode 100644
--- /dev/null
+++ b/src/applications/drydock/interface/command/DrydockWinRMCommandInterface.php
@@ -0,0 +1,76 @@
+<?php
+
+final class DrydockWinRMCommandInterface extends DrydockCommandInterface {
+
+ private $passphraseWinRMPassword;
+ private $connectTimeout;
+
+ private function openCredentialsIfNotOpen() {
+ if ($this->passphraseWinRMPassword !== null) {
+ return;
+ }
+
+ $credential = id(new PassphraseCredentialQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withIDs(array($this->getConfig('credential')))
+ ->needSecrets(true)
+ ->executeOne();
+
+ if ($credential->getProvidesType() !==
+ PassphrasePasswordCredentialType::PROVIDES_TYPE) {
+ throw new Exception('Only password credentials are supported.');
+ }
+
+ $this->passphraseWinRMPassword = PassphrasePasswordKey::loadFromPHID(
+ $credential->getPHID(),
+ PhabricatorUser::getOmnipotentUser());
+ }
+
+ public function getExecFuture($command) {
+ $this->openCredentialsIfNotOpen();
+
+ $argv = func_get_args();
+
+ $change_directory = '';
+ if ($this->getWorkingDirectory() !== null) {
+ $working_directory = $this->getWorkingDirectory();
+ if (strlen($working_directory) >= 2 && $working_directory[1] === ':') {
+ // We must also change drive.
+ $drive = $working_directory[0];
+ $change_directory .= 'cd '.$working_directory.' & '.$drive.': & ';
+ } else {
+ $change_directory .= 'cd '.$working_directory.' & ';
+ }
+ }
+
+ // Encode the command to run under Powershell.
+ $command = id(new PhutilCommandString($argv))
+ ->setEscapingMode(PhutilCommandString::MODE_POWERSHELL);
+
+ // When Microsoft says "Unicode" they don't mean UTF-8.
+ $command = mb_convert_encoding($command, 'UTF-16LE');
+ $command = base64_encode($command);
+
+ $powershell =
+ 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe';
+ $powershell .=
+ ' -ExecutionPolicy Bypass'.
+ ' -NonInteractive'.
+ ' -InputFormat Text'.
+ ' -OutputFormat Text'.
+ ' -EncodedCommand '.$command;
+
+ return new ExecFuture(
+ 'winrm '.
+ '-hostname=%s '.
+ '-username=%P '.
+ '-password=%P '.
+ '-port=%s '.
+ '%s',
+ $this->getConfig('host'),
+ $this->passphraseWinRMPassword->getUsernameEnvelope(),
+ $this->passphraseWinRMPassword->getPasswordEnvelope(),
+ $this->getConfig('port'),
+ $change_directory.$powershell);
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Thu, May 9, 9:16 PM (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6277747
Default Alt Text
D10495.diff (6 KB)

Event Timeline