Page MenuHomePhabricator

D10495.id25228.diff
No OneTemporary

D10495.id25228.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
@@ -635,6 +635,7 @@
'DrydockSFTPFilesystemInterface' => 'applications/drydock/interface/filesystem/DrydockSFTPFilesystemInterface.php',
'DrydockSSHCommandInterface' => 'applications/drydock/interface/command/DrydockSSHCommandInterface.php',
'DrydockWebrootInterface' => 'applications/drydock/interface/webroot/DrydockWebrootInterface.php',
+ 'DrydockWinRMCommandInterface' => 'applications/drydock/interface/command/DrydockWinRMCommandInterface.php',
'DrydockWorkingCopyBlueprintImplementation' => 'applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php',
'FeedConduitAPIMethod' => 'applications/feed/conduit/FeedConduitAPIMethod.php',
'FeedPublishConduitAPIMethod' => 'applications/feed/conduit/FeedPublishConduitAPIMethod.php',
@@ -3429,6 +3430,7 @@
'DrydockSFTPFilesystemInterface' => 'DrydockFilesystemInterface',
'DrydockSSHCommandInterface' => 'DrydockCommandInterface',
'DrydockWebrootInterface' => 'DrydockInterface',
+ 'DrydockWinRMCommandInterface' => 'DrydockCommandInterface',
'DrydockWorkingCopyBlueprintImplementation' => 'DrydockBlueprintImplementation',
'FeedConduitAPIMethod' => 'ConduitAPIMethod',
'FeedPublishConduitAPIMethod' => 'FeedConduitAPIMethod',
diff --git a/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php
@@ -75,19 +75,7 @@
$full_path = $base_path.$separator.$lease_id;
$cmd = $lease->getInterface('command');
-
- if ($v_platform !== 'windows') {
- $cmd->execx('mkdir %s', $full_path);
- } else {
- // Windows is terrible. The mkdir command doesn't even support putting
- // the path in quotes. IN QUOTES. ARGUHRGHUGHHGG!! Do some terribly
- // inaccurate sanity checking since we can't safely escape the path.
- if (preg_match('/^[A-Z]\\:\\\\[a-zA-Z0-9\\\\\\ ]/', $full_path) === 0) {
- throw new Exception(
- 'Unsafe path detected for Windows platform: "'.$full_path.'".');
- }
- $cmd->execx('mkdir %C', $full_path);
- }
+ $cmd->execx('mkdir %s', $full_path);
$lease->setAttribute('path', $full_path);
}
@@ -103,7 +91,12 @@
switch ($type) {
case 'command':
- return id(new DrydockSSHCommandInterface())
+ $interface = new DrydockSSHCommandInterface();
+ if ($resource->getAttribute('platform') === 'windows') {
+ $interface = new DrydockWinRMCommandInterface();
+ }
+
+ return $interface
->setConfiguration(array(
'host' => $resource->getAttribute('host'),
'port' => $resource->getAttribute('port'),
diff --git a/src/applications/drydock/interface/command/DrydockSSHCommandInterface.php b/src/applications/drydock/interface/command/DrydockSSHCommandInterface.php
--- a/src/applications/drydock/interface/command/DrydockSSHCommandInterface.php
+++ b/src/applications/drydock/interface/command/DrydockSSHCommandInterface.php
@@ -36,45 +36,10 @@
$argv = func_get_args();
- if ($this->getConfig('platform') === 'windows') {
- // Handle Windows by executing the command under PowerShell.
- $command = id(new PhutilCommandString($argv))
- ->setEscapingMode(PhutilCommandString::MODE_POWERSHELL);
+ // Handle UNIX by executing under the native shell.
+ $argv = $this->applyWorkingDirectoryToArgv($argv);
- $change_directory = '';
- if ($this->getWorkingDirectory() !== null) {
- $change_directory .= 'cd '.$this->getWorkingDirectory();
- }
-
- $script = <<<EOF
-$change_directory
-$command
-if (\$LastExitCode -ne 0) {
- exit \$LastExitCode
-}
-EOF;
-
- // When Microsoft says "Unicode" they don't mean UTF-8.
- $script = mb_convert_encoding($script, 'UTF-16LE');
-
- $script = base64_encode($script);
-
- $powershell =
- 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe';
- $powershell .=
- ' -ExecutionPolicy Bypass'.
- ' -NonInteractive'.
- ' -InputFormat Text'.
- ' -OutputFormat Text'.
- ' -EncodedCommand '.$script;
-
- $full_command = $powershell;
- } else {
- // Handle UNIX by executing under the native shell.
- $argv = $this->applyWorkingDirectoryToArgv($argv);
-
- $full_command = call_user_func_array('csprintf', $argv);
- }
+ $full_command = call_user_func_array('csprintf', $argv);
$command_timeout = '';
if ($this->connectTimeout !== null) {
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,69 @@
+<?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() !==
+ PassphraseCredentialTypePassword::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) {
+ $change_directory .= 'cd '.$this->getWorkingDirectory().' & ';
+ }
+
+ // 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
Apr 4 2025, 12:18 AM (5 w, 19 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7693639
Default Alt Text
D10495.id25228.diff (7 KB)

Event Timeline