Ansible with winrm to WindowsServer 2008 with Exchange 2010 (Command Powershell)

Hi Guys,

i’m getting crazy about this setup.

Maybe you got an idea.

I’m connecting to our Exchange/Windows servers by winrm with the domain admin user. This is working.

Running a role with the task

`

  • name: Testname
    win_command: ipconfig /all
    `

this is also working.

But i need to use winrm to execute a commad (cmdlet) inside the Exchange Management Shell…

So i tried to upload a script.ps1 to my %HOMEPATH% for the domain admin and tried to run this script there - not working, script is not found for example when i’m using full paths like c:\users\administrator.DOMAIN

So i switched back to simple names without any paths and then i got everything under my current domain admin users folder c:\users\administrator.DOMAIN\ …ok.

I uploaded a powershell script like

`
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -version 2.0 -NonInteractive -command “. ‘C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1’; Connect-ExchangeServer -auto; Get-Mailbox”

`

This is what’s inside the role/tasks/main.yml

`

  • win_file: path=ansible state=directory

  • win_copy: src=script.ps1 dest=script.ps1 force=yes

  • name: Get information about a user
    script: script.ps1
    register: output

  • debug: msg={{output}}

`

When running the task above i get

`
ok: [my_windows_host] => {
“msg”: {
“changed”: true,
“rc”: 0,
“stderr”: “TryLoadExchangeTypes : Exception calling "TryLoadExchangeTypes" with "2" argument(s): "Exception of type ‘System.OutOfM\r\nemoryException’ was thrown."\r\nAt C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:75 char:92\r\n+ $typeLoadResult = [Microsoft.Exchange.Configuration.Tasks.TaskHelper]::TryLoadExchangeTypes <<<< ($ManagementPath, $t\r\nypeListToCheck)\r\n + CategoryInfo : NotSpecified: (:slight_smile: , MethodInvocationException\r\n + FullyQualifiedErrorId : DotNetMethodException\r\n \r\nRegisterAssemblyResolver : Exception calling "RegisterAssemblyResolver" with "0" argument(s): "The type initializer for\r\n ‘Microsoft.Exchange.Data.SerializationTypeConverter’ threw an exception."\r\nAt C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:87 char:79\r\n+ [Microsoft.Exchange.Data.SerializationTypeConverter]::RegisterAssemblyResolver <<<< ()\r\n + CategoryInfo : NotSpecified: (:slight_smile: , MethodInvocationException\r\n + FullyQualifiedErrorId : DotNetMethodException\r\n \r\nUpdate-TypeData : \r\nAt C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:104 char:16\r\n+ Update-TypeData <<<< -PrependPath $partialTypeFile \r\n + CategoryInfo : InvalidOperation: (:slight_smile: [Update-TypeData], RuntimeException\r\n + FullyQualifiedErrorId : TypesXmlUpdateException,Microsoft.PowerShell.Commands.UpdateTypeDataCommand\r\n \r\nwrite-host : \r\nAt C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:170 char:16\r\n+ write-host -no <<<< $RemoteExchange_LocalizedStrings.res_full_list\r\n + CategoryInfo : WriteError: (:slight_smile: [Write-Host], ParameterBindingException\r\n + FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.WriteHostCommand\r\n \r\nwrite-host : \r\nAt C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:171 char:16\r\n+ write-host -no <<<< " "\r\n + CategoryInfo : WriteError: (:slight_smile: [Write-Host], ParameterBindingException\r\n + FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.WriteHostCommand\r\n \r\nwrite-host : \r\nAt C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:174 char:16\r\n+ write-host -no <<<< $RemoteExchange_LocalizedStrings.res_only_exchange_cmdlets\r\n + CategoryInfo : WriteError: (:slight_smile: [Write-Host], ParameterBindingException\r\n + FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.WriteHostCommand\r\n \r\nwrite-host : \r\nAt C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:175 char:16\r\n+ write-host -no <<<< " "\r\n + CategoryInfo : WriteError: (:slight_smile: [Write-Host], ParameterBindingException\r\n + FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.WriteHostCommand\r\n \r\nwrite-host : \r\nAt C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1:178 char:16\r\n+ write-host -no <<<< $RemoteExchange_LocalizedStrings.res_cmdlets_specific_role\r\n + CategoryInfo : WriteError: (:slight_smile: [Write-Host], ParameterBindingException\r\n + FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.WriteHostCommand\r\n \r\n”,
“stdout”: “The Exchange types file wasn’t loaded because not all of the required files could be found.\n\n Welcome to the Exchange Management Shell!\n\nGet-Command\nGet-ExCommand\n”,
“stdout_lines”: [
“The Exchange types file wasn’t loaded because not all of the required files could be found.”,
“”,
" Welcome to the Exchange Management Shell!",
“”,
“Get-Command”,
“Get-ExCommand”
]
}
}

`

I don’t get it why the

; Get-Mailbox

part is not executed from my script, but anything else before, what is wrong?

Is this OutOfMemory Exception because of https://support.microsoft.com/de-de/kb/2842230 ?

Any (other) ideas?

Thx

Cheers
Christian

Hi,

It is certainly possibly that the System.OutOfMemoryException is because of the lack of the hotfix you mention, which affects S2008.
Either apply the patch manually to the box or just make sure it is fully up to date with windows updates (I think the fix was rolled up into SP1 if I recall).

If you can update to WMF 4.0 on the box that would fix the problem as well, as the bug affected WMF 3.0.

Hope this helps,

Jon

Hi,

It is certainly possibly that the System.OutOfMemoryException is because of the lack of the hotfix you mention, which affects S2008.
Either apply the patch manually to the box or just make sure it is fully up to date with windows updates (I think the fix was rolled up into SP1 if I recall).

If you can update to WMF 4.0 on the box that would fix the problem as well, as the bug affected WMF 3.0.

Hope this helps,

Jon

Well i’m not able to update the system right now.

But what i find out:

I can run this here directly on the Windows Server bei right click and run with powershell

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -version 2.0 -NonInteractive -command "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010; Get-Mailbox >> ansible.txt"

But uploading this script and run it by

`

  • name: Get information about a user
    script: script.ps1
    `

it is not working and i dont know why…did i make a general mistake.

Cheers
Christian

The underlying issue you’re probably hitting is that Microsoft doesn’t really support using Exchange cmdlets outside a PSRP session. I did some prototyping recently against building/managing Exchange 2016 with Ansible, and got it working. What you have to do is inject a PS-native PSRP session in the middle (which is why you need to have Kerberos delegation turned on via ansible_winrm_kerberos_delegtion=true). You’ll have to use kerberos delegation + Invoke-Command via raw or win_shell, eg:

win_shell: Invoke-Command -ConnectionUri $cu -Authentication Kerberos -ConfigurationName Microsoft.Exchange -ScriptBlock { Get-ExchangeServer }

Ansible/pywinrm aren’t currently PSRP-based, just straight WinRM/WinRS (analogous to running stuff via winrs.exe).

-Matt

I’m already at the point where i nearly know what to do. The question is, how should i do this.

I think there is a mistake by me inside my “powershell” script to run…i would like to know, what exactly win_command and win_shell makes the difference, or raw…or script…

Any of them can work- the key is making sure that kerberos delegation is working correctly. I’d suggest using something simple like “win_shell: Get-ChildItem \someserver\share” to smoke-test that delegation is working.

You probably don’t want win_command (which just launches a process, so you’d be running Powershell and pointing it at a script yourself). Any of the other three should be fine and assume Powershell by default- script will expect to push a script over from the controller and exec it, while raw/win_shell will execute whatever you use just as if you’d typed it in Powershell. Raw runs with less overhead (since it’s basically just running a Powershell command remotely without pushing any code to the target), but win_shell supports the creates/removes args and switchable executables (and may support other goodies down the line where raw never will).