To improve security with our solutions, we use VNets on all our Azure subscriptions and do not expose remote desktop port (3389) publicly. Since internal endpoints are only reachable within a Cloud Service, this reduce the possible surface of attack.
Connect to Cloud Services instances / Virtual machines without having to go in the Azure portal
We needed a way to export all the virtual machines and cloud services role instances for an Azure subscription without having to go in the Azure portal to get the RDP files. For us, it would not have worked anyway since the rdp file that the portal generate point to the cloudapp.net address.
For our need, we use the private IP address of the instances but you can easily change the script to use the public DNS name instead.
How to do that
First, you select your subscription
Select-AzureSubscription -SubscriptionName $SubscriptionName
The script
#requires -Version 3.0 -Module Azure
[CmdletBinding(DefaultParametersetName='NoExport')]
param(
[Parameter(Position=0, Mandatory=$true, ParameterSetName='NoExport')]
[Parameter(Position=0, Mandatory=$true, ParameterSetName='ExportRdp')]
[string]
$SubscriptionName,
[Parameter(Position=1, ParameterSetName='NoExport')]
[Parameter(Position=1, ParameterSetName='ExportRdp')]
[string]
$ServiceName,
[Parameter(Position=2, ParameterSetName='ExportRdp')]
[Switch]
$ExportRdp,
[Parameter(Position=3, Mandatory=$true, ParameterSetName='ExportRdp')]
[System.IO.DirectoryInfo]
$RdpOutputDirectory
)
$ErrorActionPreference = 'Stop'
Import-Module Azure
Write-Verbose "Using subscription $SubscriptionName"
Select-AzureSubscription -SubscriptionName $SubscriptionName
if($ServiceName) {
Write-Verbose "Querying cloud service $ServiceName"
$services = Get-AzureService -ServiceName $ServiceName
}
else {
Write-Verbose "Querying all cloud services."
$services = Get-AzureService
}
Write-Verbose "Getting deployments informations."
$result = $services | Get-AzureDeployment -ErrorAction SilentlyContinue | % {
$svcName = $_.ServiceName
$_.RoleInstanceList | % {
@{ ServiceName=$svcName; RoleName=$_.RoleName; InstanceName=$_.InstanceName; IpAddress=$_.IPAddress }
}
}
if($ExportRdp) {
$RdpOutputDirectory.Create()
$dir = $RdpOutputDirectory.CreateSubdirectory("RDP-$SubscriptionName")
Write-Verbose "Exporting rdp files to directory '$($dir.FullName)'."
$result | % {
$outputFilename = '{0}\{1}.{2}.{3}.rdp' -f $dir.FullName, $_.ServiceName, $_.RoleName, $_.InstanceName
"full address:s:$($_.IpAddress)`r`nLoadBalanceInfo:s:Cookie: mstshash=$($_.RoleName)#$($_.InstanceName)" | Out-File $outputFilename
}
}
$result
What it does is really simple, it loop through all deployments of all cloud services inside your subscription and construct an array of objects containing the service name, role name, instance name and ip address.
If you use the ExportRdp switch you need to provide a mandatory RdpOutputDirectory parameter in which rdp files will be exported.
Rdp files will have the following naming pattern: {ServiceName}.{RoleName}.{InstanceName}.rdp
You can easily change this script to modify the generated rdp to include a default username by adding the following line
username:s:{RdpUsername}
where {RdpUsername} is the username
What you'll need
- An Azure subscription with at least one cloud services (can be a role or virtual machine)
- Azure PowerShell CmdLet
Let me know what you think!