Friday, December 5, 2014

Use PowerShell to Create Azure VMs for CRM with ADFS

I wanted to share a couple PowerShell scripts for creating Microsoft Azure virtual machines that have Reserved (static) IP addresses. Normally for testing purposes you could probably get away without a static IP but if you are looking to create a CRM server with ADFS it definitely helps because of the need to have external DNS records pointing at the server. If you spin up a VM right from the web, each time you start it up it's assigned a new external IP address. Through the Azure Portal there isn't an option to assign a Reserved IP address so you'll need to use something like PowerShell to do it.

A couple things to point out right away. The first deals with pricing, you are allowed 5 free Reserved IP address per subscription. They are only free if you have them assigned to something. If you reserve an IP and don't use it you will incur costs. The second thing is that you aren't directly able to assign a Reserved IP address to an existing VM. More on that later.

If you don't have an existing VM built you can create one with PowerShell and give it a Reserved IP address right away. You'll need to execute the steps individually as long the way you'll need to fill in information based on your own subscription, I've made it so you should be able to get everything you need from the script but you could certainly log into the Azure Portal and get some of these values as well.

<# Make sure you have installed the Azure PowerShell cmdlets: https://www.windowsazure.com/en-us/manage/downloads/ and then reboot #>

<# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    The steps need to be run individually 
   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #>

<# Step 1: Run this first to download your publisher file from Azure #>
Get-AzurePublishSettingsFile

<# Step 2: Change the path to the file you downloaded: C:\xxx\xxx.publishsettings #>
$publisherFileLocation = "C:\xxx\xxx.publishsettings"
Import-AzurePublishSettingsFile $publisherFileLocation

<# Step 3: Input the 'Name' of the subscription from the output of the previous step #>
$subscriptionName = "Visual Studio Ultimate with MSDN"
Select-AzureSubscription -SubscriptionName $subscriptionName

<# Step 4: Run this to output the list of Azure storage accounts associated with your account #>
Get-AzureStorageAccount 

<# Step 5: Input the subscription 'Name' again and the 'StorageAccountName' from the output of the previous step
when the VM gets created it will use that Azure Storage account #>
$sortageAccountName = "portalxxxxxxxxxxxxxxxxx" 
Set-AzureSubscription -SubscriptionName $subscriptionName -CurrentStorageAccount $sortageAccountName

<# Step 6: Create a reserved/static IP for your VM - input the name/label and the region your VM will be in #>
$reservedIPName = "CRMIP"
$reservedIPLabel = "CRMIP"
$location = “North Central US” 
New-AzureReservedIP –ReservedIPName $reservedIPName –Label $reservedIPLabel –Location $location
<# Use this to remove the reserved IP if you end up not needing it #>
<# Remove-AzureReservedIP -ReservedIPName "CRMIP" -Force# >
<# Show the list of reserved IP addresses if you are interested #>
<# Get-AzureReservedIP #>

<# Step 7: Run this to output the list of Azure VM images to base the server on, Windows Server 2012 R2 for example #>
$images = Get-AzureVMImage
$images | where {$_.Label -like 'windows server 2012 r2*'} | select Label, RecommendedVMSize, PublishedDate | Format-Table -AutoSize

<# Step 8: Input the the 'Label' and 'Publish Date' of the specific image you want to start with #>
$vmImage = Get-AzureVMImage `
    | Where-Object -Property ImageFamily -ilike "Windows Server 2012 R2*" `
    | Sort-Object -Descending -Property PublishedDate `
    | Select-Object -First(1)

Write-Output $imageName

<# Step 9: Input the VM & cloud service names, VM size, and admin username & password and create the VM #>
$vmName = "CRM2015"
$cloudServiceName = "CRM2015"
$instanceSize = "ExtraLarge"
$adminUsername = "crmadmin"
$adminPassword = "Str0ngP@ssw0rd?"
New-AzureVMConfig -Name $vmName -InstanceSize $instanceSize -ImageName $vmImage.ImageName | 
    Add-AzureProvisioningConfig -Windows -AdminUsername $adminUsername -Password $adminPassword |
    Add-AzureEndpoint -Name "HTTP" -Protocol "tcp" -PublicPort 80 -LocalPort 80 | 
    Add-AzureEndpoint -Name "HTTPS" -Protocol "tcp" -PublicPort 443 -LocalPort 443 |
    Add-AzureEndpoint -Name "HTTPS2" -Protocol "tcp" -PublicPort 444 -LocalPort 444 | <# Only if you need ADFS on the same server #>
    Add-AzureEndpoint -Name "Remote Desktop" -Protocol "tcp" -PublicPort 60523 -LocalPort 3389 |
    New-AzureVM -ServiceName $cloudServiceName -ReservedIPName $reservedIPName -Location $location

You can download the script here: https://gist.github.com/jlattimer/cb2f0d7e80d06ba73f10

If you have an existing VM that you'd like to use you'll need to first capture an image of the existing machine as you'll need to delete it and re-create it with the script. You can do that in the Azure Portal by using the "Capture" option under the specific VM, just remember what you named the image because you'll need to reference that later. Once you've saved the image delete the VM and associated Could Service (assuming nothing else if using it) and proceed with the script.
<# Make sure you have installed the Azure PowerShell cmdlets: https://www.windowsazure.com/en-us/manage/downloads/ and then reboot #>

<# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    The steps need to be run individually 
   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #>

<# Step 1: Run this first to download your publisher file from Azure #>
Get-AzurePublishSettingsFile

<# Step 2: Change the path to the file you downloaded: C:\xxx\xxx.publishsettings #>
$publisherFileLocation = "C:\xxx\xxx.publishsettings"
Import-AzurePublishSettingsFile $publisherFileLocation

<# Step 3: Input the 'Name' of the subscription from the output of the previous step #>
$subscriptionName = "Visual Studio Ultimate with MSDN"
Select-AzureSubscription -SubscriptionName $subscriptionName

<# Step 4: Run this to output the list of Azure storage accounts associated with your account #>
Get-AzureStorageAccount 

<# Step 5: Input the subscription 'Name' again and the 'StorageAccountName' from the output of the previous step
when the VM gets created it will use that Azure Storage account #>
$sortageAccountName = "portalxxxxxxxxxxxxxxxxx" 
Set-AzureSubscription -SubscriptionName $subscriptionName -CurrentStorageAccount $sortageAccountName

<# Step 6: Create a reserved/static IP for your VM - input the name/label and the region your VM will be in #>
$reservedIPName = "CRMIP"
$reservedIPLabel = "CRMIP"
$location = “North Central US” 
New-AzureReservedIP –ReservedIPName $reservedIPName –Label $reservedIPLabel –Location $location
<# Use this to remove the reserved IP if you end up not needing it #>
<# Remove-AzureReservedIP -ReservedIPName "CRMIP" -Force# >
<# Show the list of reserved IP addresses if you are interested #>
<# Get-AzureReservedIP #>

<# Step 7: Use this to list your existing Azure VM images #>
Get-AzureVMImage | Where-Object { $_.Category -eq "User" } 

<# Step 8: Input the VM & cloud service names, VM size, Image name and create the VM #>
$vmName = "CRM2015"
$imageName = "ExistingCRM2015-12032014"
$cloudServiceName = "CRM2015"
$instanceSize = "ExtraLarge"

New-AzureVMConfig -Name $vmName -InstanceSize $instanceSize -Image $imageName | 
    Add-AzureEndpoint -Name "HTTP" -Protocol "tcp" -PublicPort 80 -LocalPort 80 | 
    Add-AzureEndpoint -Name "HTTPS" -Protocol "tcp" -PublicPort 443 -LocalPort 443 |
    Add-AzureEndpoint -Name "HTTPS2" -Protocol "tcp" -PublicPort 444 -LocalPort 444 | <# Only if you need ADFS on the same server #>
    Add-AzureEndpoint -Name "Remote Desktop" -Protocol "tcp" -PublicPort 60523 -LocalPort 3389 |
    New-AzureVM -ServiceName $cloudServiceName -ReservedIPName $reservedIPName -Location $location

You can download the script here: https://gist.github.com/jlattimer/95b4fe9d1913de018922