0
votes

I've been trying to get the pywinrm module to run the New-Mailbox Powershell cmdlet remotely. This is what I have so far:

import winrm

ps_text = "$pass = ConvertTo-SecureString -String '%s' -AsPlainText -Force; \
                Add-PSSnapIn Microsoft.Exchange.Management.Powershell.E2010; \
                New-Mailbox -UserPrincipalName '%[email protected]' \
                -Alias '%s' -Name '%s' -Password $pass \
                -Firstname '%s' \
                -Lastname '%s' \
                -DisplayName '%s' \
                -PrimarySmtpAddress '%s'" % \
                ('password123',
                 'jfd',
                'john.doe',
                'John Doe',
                'John',
                'Doe',
                'John Doe',
                '[email protected]')

remote = winrm.Session('https://contoso.co.uk:5986', auth=('ps_remote', 'irrelevant'))
r = remote_session.run_cmd("powershell", ["-version", "2.0", "-c", ps_text])

This is the output I get:

New-Mailbox : Value cannot be null. Parameter name: serverSettings At line:1 char:147 + $pass = ConvertTo-SecureString -String 'password123' -AsPlainText -Force; Add-PSSnapIn Microsoft.Exchange.Management.Powershell.E2010; New-Mailbox <<<< -UserPrincipalName '[email protected]' -Alias 'john.doe' -Name 'John Doe' -Password $pass -Firstname 'John' -Lastname 'Doe' -DisplayName 'John Doe' -PrimarySmtpAddress '[email protected]' + CategoryInfo : NotSpecified: (:) [New-Mailbox], ArgumentNullException + FullyQualifiedErrorId : System.ArgumentNullException,Microsoft.Exchange.Management.RecipientTasks.NewMailbox

I figure it doesn't like $pass being unquoted, so I then wrap it in single quotes and get:

New-Mailbox : Cannot bind parameter 'Password'. Cannot convert the "$pass" value of type "System.String" to type "System.Security.SecureString".At line:1 char:231 + $pass = ConvertTo-SecureString -String 'password123' -AsPlainText -Force; Add-PSSnapIn Microsoft.Exchange.Management.Powershell.E2010; New-Mailbox -UserPrincipalName '[email protected]' -Alias 'john.doe' -Name 'John Doe' -Password <<<< '$pass' -Firstname 'John' -Lastname 'Doe' -DisplayName 'John Doe' -PrimarySmtpAddress '[email protected]' + CategoryInfo : InvalidArgument: (:) [New-Mailbox], ParameterBindingException + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.Exchange.Management.RecipientTasks.NewMailbox

Emphasis mine. And now it interprets it literally instead of expanding the $pass variable. Is there any way I can get this correctly executed?

Some notes:

  • I'm not using the documented run_ps method of winrm.Session as it does not run against the correct version of Powershell on the remote side (version 2.0 is required here as that's what the Exchange Management Snap-in requires).
  • I have tried using the low level API of pywinrm as detailed on the package page, but it's no good.
  • If I insert $pass; after first line of Powershell, the standard output does actually return System.Security.SecureString, which makes it even weirder that it would complain about a null argument in the first example.
  • I have tried wrapping in triple quotes, and swapping quote styles. No dice.
  • I have tried various other methods, including making subprocess calls to a local Powershell to run New-PSSession to import the remote session, but this fails to actually get access to the cmdlet I need. I've also tried running script blocks remotely using Invoke-Command, but even though that supposedly imports the Snap-in successfully, it doesn't run the actual cmdlet.
  • A pure Python solution would be preferable (hence the use of pywinrm), but I'm open to anything at this stage. Examples of running New-Mailbox remotely are pretty sparse, or maybe my Google-fu is weak in this instance.
1

1 Answers

0
votes

In PowerShell, single quotes will prevent variable expansion from occurring.

My recommendation would be:

  • Remove the single quotes from the $pass
  • Notice in the error message you posted, that the error is coming from -serverSettings, not -Password
  • Pass in a value for -serverSettings (I couldn't find this parameter in Exchange documentation, but check if it exists or not in your version)
  • Validate the PowerShell command on a Windows system, before attempting to issue the command through pywinrm

Hope this helps! Cheers