Tuesday, August 11, 2015

Import Azure Cloud Services into Microsoft Remote Desktop Connection Manager

This will be my first adventure into Windows PowerShell for Azure.

Firstly, we are going to have to install PowerShell for Azure. The instructions can be found here:

https://azure.microsoft.com/en-us/documentation/articles/powershell-install-configure/#Install

The actual download link is here:

http://go.microsoft.com/fwlink/p/?linkid=320376&clcid=0x409

Once that is done, the next stage is to get your 'Azure Publish Settings File' which is a file used to tell your PowerShell session how to connect to your subscription. Open your new Azure PowerShell console and type:

Get-AzurePublishSettingsFile

This will open a browser and ask you to logon with appropriate rights. Note - if you already have a browser window open with a logged in session, it will just take you to the right page. This page will trigger the download of a file, the name of which will show your subscription and today's date. Mine looked something like this:

MyCoolSubscriptionName-8-11-2015-credentials.publishsettings

At this point you can import the publish settings file into your PowerShell session using the command:

Import-AzurePublishSettingsFile <path to your publish settings file>

Here is a look at my experience (sanitized to protect my employer and randomizing account numbers)

Import-AzurePublishSettingsFile 'c:\OurAzure-8-11-2015-credentials.publishsettings'

VERBOSE: Setting: Microsoft.Azure.Common.Authentication.Models.AzureSubscription as the default and current subscription. To view other subscriptions use Get-AzureSubscription


Id          : 06600807-8638-9358-3734-8403774938749
Name        : OurAzure
Environment : AzureCloud
Account     : 87YNGH9839G659U883HNVIEJPEEVPN906UPNV0N3
Properties  : {[SupportedModes, AzureServiceManagement]}

As the output suggests, if you have more than one subscription you can issue the following command:

Get-AzureSubscription

I only have one, so here is the sanitized output that I receive from that command:

SubscriptionId           : 06600807-8638-9358-3734-8403774938749
SubscriptionName         : OurAzure
Environment              : AzureCloud
SupportedModes           : AzureServiceManagement
DefaultAccount           : 87YNGH9839G659U883HNVIEJPEEVPN906UPNV0N3
Accounts                 : 87YNGH9839G659U883HNVIEJPEEVPN906UPNV0N3
IsDefault                : True
IsCurrent                : True
CurrentStorageAccountName:
TenantId                 :

Next its time to run the script, which I cannot take credit for. Credit goes to Stuart Leeks at Microsoft.

https://social.msdn.microsoft.com/profile/stuartle/

When the script is ran it will create 'AzureVMs.rdg' which can be opened by Remote Desktop Connection Manager. Here is a screenshot of my finished result:




Here is the script:

$rdcmanName = "Azure VMs"
$outputFileName = Get-Location | Join-Path -ChildPath "AzureVMs.rdg"

$xml = [xml]'<?xml version="1.0" encoding="utf-8"?>
<RDCMan programVersion="2.7" schemaVersion="3">
  <file>
    <credentialsProfiles />
    <properties>
      <expanded>True</expanded>
      <name>Azure VMs</name>
    </properties>
    <encryptionSettings inherit="None">
      <encryptionMethod>LogonCredentials</encryptionMethod>
      <credentialName></credentialName>
      <credentialData />
    </encryptionSettings>
    <group>
      <properties>
        <expanded>False</expanded>
        <name>groupname</name>
      </properties>
      <server>
        <properties>
          <displayName>displayname</displayName>
          <name>servername</name>
        </properties>
        <connectionSettings inherit="None">
          <connectToConsole>False</connectToConsole>
          <startProgram />
          <workingDir />
          <port>12345</port>
          <loadBalanceInfo></loadBalanceInfo>
        </connectionSettings>
      </server>
    </group>
  </file>
  <connected />
  <favorites />
  <recentlyUsed />
</RDCMan>'

$fileElement =$xml.RDCMan.file
$groupTemplateElement =$xml.RDCMan.file.group
$serverTemplateElement = $groupTemplateElement.server
$fileElement.properties.name = $rdcmanName
function getDisplayName($name){
    $name.Replace("http://", "").Replace("https://","").TrimEnd('/')
}
function addServerElementToGroup($group, $name, $displayName, $port, $loadBalanceInfo){
    $serverElement = $serverTemplateElement.Clone()
    $serverElement.properties.name = getDisplayName $name
    $serverElement.properties.displayName = $displayName

    $serverElement.connectionSettings.port = $port.ToString()
    if ($loadBalanceInfo -ne $null){
        $serverElement.connectionSettings.loadBalanceInfo = $loadBalanceInfo
    }
    $group.AppendChild($serverElement) | out-null
}
function getGroup($element, $groupName){
    $group = $xml.RDCMan.file.group | ?{ $_.properties.name -eq $groupName} | Select-Object -First 1
    if ($group -eq $null){
        $group = $groupTemplateElement.Clone()
        $group.properties.name = $groupName
        $group.RemoveChild($group.server)
        $element.AppendChild($group) | out-null
    }
    return $group
}
function addServer(){
    param(
   [Parameter(Mandatory=$True,
   ValueFromPipeline=$True)]
   [object[]]$info
   )
    process{
        $group = getGroup $fileElement $info.ServiceName
        if ($info.RoleName -ne $null) {
            $group = getGroup $group $info.RoleName
        }
        if ($info.Slot -ne $null) {
            $group = getGroup $group $info.Slot
        }
        addServerElementToGroup $group $info.Name $info.DisplayName $info.Port $info.LoadBalanceInfo
    }
}

Get-AzureService | %{
    $service = $_
    $serviceName = $service.ServiceName

    Get-AzureVM -ServiceName $serviceName -ErrorAction Ignore | %{
        $vm = $_
        $rdpEndpoints = @($vm.VM.ConfigurationSets.InputEndpoints | ?{$_.LocalPort -eq 3389})
        if($rdpEndpoints.Length -gt 0){
            New-Object PSObject -Property @{
                ServiceName = $serviceName
                Name = $vm.DNSName
                DisplayName = $vm.Name
                Port = $rdpEndpoints[0].Port
            }
        }
    }

    $production = @(Get-AzureDeployment -ServiceName $serviceName -Slot Production -ErrorAction SilentlyContinue)
    $staging = @(Get-AzureDeployment -ServiceName $serviceName -Slot Staging -ErrorAction SilentlyContinue)
    $combined = $production + $staging
    $combined | %{
        $deployment = $_
        $deployment.RoleInstanceList | ?{
                ($_.InstanceEndpoints | ?{$_.Port -eq 3389}).Count -gt 0
            } | %{
            $roleInstance = $_
            New-Object PSObject -Property @{
                ServiceName = $serviceName
                Name = $deployment.Url.ToString()
                RoleName = $roleInstance.RoleName
                Slot = $deployment.Slot
                DisplayName = $roleInstance.InstanceName
                Port = 3389
                LoadBalanceInfo = "Cookie: mstshash=" + $roleInstance.RoleName + "#" + $roleInstance.InstanceName
            }
        }
    }
} | addServer # add to the tree

$fileElement.RemoveChild($groupTemplateElement) | out-null

$xml.Save($outputFileName)




Cheers!

No comments:

Post a Comment