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_psmethod ofwinrm.Sessionas 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 returnSystem.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-PSSessionto import the remote session, but this fails to actually get access to the cmdlet I need. I've also tried running script blocks remotely usingInvoke-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-Mailboxremotely are pretty sparse, or maybe my Google-fu is weak in this instance.