Skip to main content

PowerShell + Azure + Exchange - Connect Remotely

My recent dive into the Mobile Device & Email Management space has presented me with an opportunity to learn Exchange & Office 365.

I have built up an Azure VM running Server 2008 R2 with Exchange 2010 Server on it. It didn't made a whole lot of sense to connect to the machine using RDP and then running cmdlets on Exchange Management Shell.


Well I must admit that I tried opening a normal PSSession and importing the Exchange cmdlets in there but that didn't work as the Microsoft.Exchange endpoint configuration is hosted on IIS.

So here are the steps I followed to get the Exchange cmldets via Implicit Remoting, this is very similar to what we do with Office 365. This is a beginner post as am still wrapping my head around Exchange ;)

Open the endpoint on the cloud service to allow the HTTPS traffic to your Exchange Server. Here is how the endpoints appear for my Exchange box.



Note that the Public and Private port are both 443 which means when I try reach my cloud service on port 443 it will essentially redirect the request to my Exchange Box.


If you don't have that endpoint open then you need to use the cmdlet Add-AzureEndpoint to do that.

Another thing we need to do is allow Basic authentication for the \PowerShell virtual directory on the Exchange Server. This is straight forward, open the IIS Manager and click on the Authentication for the Virtual Directory :




Now Right click on the Basic Authentication and "Enable" it.




We can even do this using PowerShell for IIS :)

We are using basic authentication because my machine from which I will try to use Remote PowerShell to connect to my Exchange Server is not part of the domain.

All done, now time to try opening a PSSession to the Exchange Server.

let's store the Credentials in a variable first:


001
$creds = Get-Credential -Message 'Enter the Exchange Admin Credentials'

Now let's use the New-PSSession cmdlet to connect to the PowerShell endpoint using the connection URI for the cloud service and the Configuration name to which we connect is Microsoft.Exchange.

Note : As already pointed out, we will be using the basic authentication. 



PS>New-PSSession -ConnectionUri 'https://dexterposhcloudservice.cloudapp.net/PowerShell' -ConfigurationName 'Microsoft.Exchange' -Authentication Basic -Credential $creds
New-PSSession : [dexcloudservice.cloudapp.net] Connecting to remote server dexterposhcloudservice.cloudapp.net failed with the
following error message : The server certificate on the destination computer (dexterposhcloudservice.cloudapp.net:443) has the
following errors:
The SSL certificate is signed by an unknown certificate authority.
The SSL certificate contains a common name (CN) that does not match the hostname. For more information, see the
about_Remote_Troubleshooting Help topic.

Take a look at the Error thrown it clearly tells that the Certificate which is used to connect over SSL (we are using https in the connection uri ) is signed by an unknown CA -- this is evident from the fact that on the Exchange Server the binding for the default site uses the Certificate issued by Exchange Server.

Below is the binding for port 443 on my Exchange Server (on IIS).



Look at the second error telling that the Common Name does not match the hostname of the cloud service used to connect to, makes sense as we are not using the certificate issued to our Cloud Service here but the cert issued by Exchange Server.

So let's use New-PSSessionOption cmdlet to skip the CA & CN check
PS>$PSSessionOption = New-PSSessionOption -SkipCNCheck -SkipCACheck 
PS>New-PSSession -ConnectionUri 'https://dexterposhcloudservice.cloudapp.net/PowerShell' -ConfigurationName 'Microsoft.Exchange' -Credential $creds -SessionOption $PSSessionOption -Authentication Basic

 Id Name            ComputerName    State         ConfigurationName     Availability
 -- ----            ------------    -----         -----------------     ------------
 10 Session10       dexterposhcl... Opened        Microsoft.Exchange       Available


Voila ! I have the Remote PowerShell session established to Exchange. Now time to load the Exchange Module using the Implicit Remoting.


PS>Import-PSSession -Session (Get-PSSession)
WARNING: The names of some imported commands from the module 'tmp_h5mgeuko.1ux' include unapproved verbs that might make
them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose
parameter. For a list of approved verbs, type Get-Verb.

ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     1.0        tmp_h5mgeuko.1ux                    {Add-ADPermission, Add-AvailabilityAddressSpace, Add-Content...

It will take some time and once done you will get all the Exchange cmdlets available to you based on your Role.


One more thing if you don't wanna do all the above steps again and again then you can use Export-PSSession to dump the module locally and just import it next time.

Here is how you do it :


PS>Export-PSSession -Session (Get-PSSession) -OutputModule AzureExchange


    Directory: C:\Users\DDhami\Documents\WindowsPowerShell\Modules\AzureExchange


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---         11/1/2014   5:04 PM     252399 AzureExchange.format.ps1xml
-a---         11/1/2014   5:04 PM        592 AzureExchange.psd1
-a---         11/1/2014   5:04 PM    1534799 AzureExchange.psm1

This will put a Module name AzureExchange in your Modules directory and next time you Import the module it will prompt you for credentials to enter and then use those to open a PSSession



Thanks for reading fellas. If you have an Exchange Lab up on Azure then do use this tip :)

Now the gotcha with using Implicit Remoting is that I get de-serialized objects back. I remember this from one of the session on Exchange by Sahal Omar for PSBUG.

So on my local machine the below is seen:





While on the Exchange Management Shell , I see this :




I must say that after having worked to automate bits of ConfigMgr with PowerShell, working with Exchange is really Cool. The integration is superb !


Popular posts from this blog

Test connectivity via a specific network interface

Recently while working on a Private cloud implementation, I came across a scenario where I needed to test connectivity of a node to the AD/DNS via multiple network adapters.  Many of us would know that having multiple network routes is usually done to take care of redundancy. So that if a network adapter goes down, one can use the other network interface to reach out to the node. In order to make it easy for everyone to follow along, below is an analogy for the above scenario: My laptop has multiple network adapters (say Wi-Fi and Ethernet) connected to the same network. Now how do I test connectivity to a Server on the network only over say Wi-Fi network adapter?

PowerShell + SCCM : Run CM cmdlets remotely

Today I saw a tweet about using implicit remoting to load the Configuration Manager on my machine by Justin Mathews . It caught my eye as I have never really tried it, but theoretically it can be done. Note - The second tweet says "Cannot find a provider with the name CMSite", resolution to which is in the Troubleshooting section at the end.

PowerShell : Trust network share to load modules & ps1

Problem Do you have a central network share, where you store all the scripts or PowerShell modules ? What happens if you try to run the script from a network share ? or if you have scripts (local) which invoke scripts or import PowerShell modules stored on this network share ? Well you would see a security warning like below (Note - I have set execution policy as 'Unrestricted' not 'bypass' here): Run a .ps1 from the network share Well this is a similar warning, which you get when you download scripts from Internet. As the message says run Unblock-File cmdlet to unblock the script and then run it, let's try it.