Audit Azure ARM Networks

Consultants love to audit environments and there is no better use of a script than for this purpose. There are some great Azure tools for monitoring and auditing environments. I encourage my customers to make use of the extensive capabilities that exist in OMS.

However you arrive on site and need to document what exists and where and in this instance PowerShell is once again for friend.

This script lists out the virtual networks and subnets in a subscription.  Remember there is always a better way to do things and if you have a better way don’t forget to share.

$FindNetworks = Find-AzureRmResource | where {$_.ResourceType -like "Microsoft.Network/VirtualNetworks"}</code>

$out = @()

Foreach ($Network in $FindNetworks)
{
$Name = $Network.Name
$ResourceType = $Network.ResourceId
$ResourceGroupName = $Network.ResourceGroupName
$Location = $Network.Location

$VNetDetail = Get-AzureRmvirtualNetwork -Name $Network.Name -ResourceGroupName $Network.ResourceGroupName

$props = @{

VNetName = $Network.Name
ResourceGroup = $Network.ResourceGroupName
Location = $Network.Location
AddressSpace = $VNetDetail.AddressSpace.AddressPrefixes
Subnets = $VNetDetail.Subnets

}
$out += New-Object PsObject -Property $props
}
$out | Format-Table -AutoSize -Wrap  VNetName, AddressSpace, Subnets, ResourceGroup, Location
$out | Out-GridView -Passthru

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Hybrid Use Benefit from Image | Azure

Please see post Hybrid Use Benefit HUB | Azure for details on the Microsoft HUB process.

I have been using a slight edit on the process described so thought I would place the code I have been using below.

Please note HUB images are now available in Azure, therefore a generalised image is no longer required.

#login into azure and select the right subscription
Login-AzureRmAccount
Get-AzureRmSubscription
Select-AzureRmSubscription

#upload HUB file
$RGName = "Resource Group Name"
    $urlOfUploadedImageVhd = "https://storageaccountname.blob.core.windows.net/container/imagename.vhd"
    Add-AzureRmVhd -ResourceGroupName $rgName -Destination $urlOfUploadedImageVhd -LocalFilePath "C:\Source\imagename.vhd" 

#Create VM using image
$Cred = Get-Credential #Don't forget needs to be complex
$vmName = "Name of VM"
$StorageAccount = Get-AzureRmStorageAccount -ResourceGroupName $RGName -name "Resource Group Name"
$OSDiskName = "$vmName-C-01" 
$nicname = "Nic01-$vmName-Prod"
$OSDiskUri = $StorageAccount.PrimaryEndpoints.Blob.ToString() + "vhds/" + $OSDiskName + ".vhd" #Name & path of new VHD
$URIofuploadedImage = $StorageAccount.PrimaryEndpoints.Blob.ToString() + "image container/image.vhd" #location of template VHD
$Location= "Azure location"

#Networking 
$Vnet = Get-AzureRmVirtualNetwork -Name "Virtual Network Name" -ResourceGroupName $RGName
$SubnetProduction = Get-AzureRmVirtualNetworkSubnetConfig -Name "Sub-1" -VirtualNetwork $Vnet
$Nic = New-AzureRmNetworkInterface -ResourceGroupName $RGName -Name $Nicname -Subnet $SubnetProduction -Location $Location

#Define VM Configuration
$VMConfig = New-AzureRmVMConfig -VMName $vmName -VMSize "Standard_DS2" |
    Set-AzureRmVMOperatingSystem -Windows -ComputerName $vmName -Credential $Cred -ProvisionVMAgent -EnableAutoUpdate |
    Set-AzureRmVMOSDisk -Name $OSDiskName -VhdUri $OSDiskUri -CreateOption FromImage -SourceImageUri $URIofuploadedImage -Windows |
    Add-AzureRmVMNetworkInterface -Id $Nic.ID -Primary

#Create VM
New-AzureRmVM -ResourceGroupName $RGName -Location $Location -LicenseType "Windows_Server" -VM $VMConfig

#Check license type of new VM
Get-AzureRmVM -ResourceGroupName $RGName -Name $vmName | Format-Table -AutoSize Name, LicenseType, Location, ProvisioningState

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Azure PowerShell Scripts

Audit Power State of all VMs | Azure PowerShell

I was recently asked to quickly audit a customer’s environment for all running VMs.  I quickly reached for my PowerShell toolbox and put together the following script.

In the example below I have used the table a grid views available.  It would be just as easy to push all this info to a csv file. For swiftness this was my approach, I’d be very interested to hear for the gurus out there to see what your preference is and how you would do this.

Remember there is always a better way, just don’t keep that to yourself!

$FindVMs = Find-AzureRmResource | where {$_.ResourceType -like "Microsoft.Compute/virtualMachines"}
 
$out = @()
 
Foreach ($vm in $Findvms)
{
$Name = $VM.Name
$ResourceId = $VM.ResourceId
$ResourceGroupName = $VM.ResourceGroupName
$Location = $VM.Location
 
$VMDetail = Get-AzureRmVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -Status
$props = @{
 
VMName = $VM.Name
ResourceGroup = $VM.ResourceGroupName
Location = $VM.Location
PowerState = $VMDetail.Statuses[1].DisplayStatus
}
$out += New-Object PsObject -Property $props
}
$out | Format-Table -AutoSize -Wrap  ResourceGroup, Location, VMName,Powerstate
$out | Out-GridView -Passthru

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Hybrid Use Benefit HUB | Azure

I have a number of customers implementing HUB benefit for their IaaS VMs in Azure.  In all cases to date this is a rebuild or new build as part of a migration.  It works very well, if licensed, you should definitely be looking at this option to drive down costs.

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Creating a VM from an Azure Image | Azure – Existing Network

I recently created a script to create a VM from an existing disk in Azure, using the v2 or ARM model.

This script created a new network but in most instances a network will already exist and although you will create a new NIC you will want to place this VM into an existing subnet.

The extract below can be used to create a new NIC but add this to a named vNet and Subnet.
When you define the VM configuration you would use this to be the NIC.
Finally make sure this (if the first NIC) is set as -Primary


#Networking
$NicName = $vmName + "NIC-Prod"
$Vnet = Get-AzureRmVirtualNetwork -Name "hubsydvnet" -ResourceGroupName $RGName
$SubnetProduction = Get-AzureRmVirtualNetworkSubnetConfig -Name "Sub-1" -VirtualNetwork $Vnet
$Nic = New-AzureRmNetworkInterface -ResourceGroupName $RGName -Name $NicName -Subnet $SubnetProduction -Location $Location

#Define VM Configuration
$VMConfig = New-AzureRmVMConfig -VMName $vmName -VMSize "Standard_DS2_v2" |
Set-AzureRmVMOperatingSystem -Windows -ComputerName $vmName -Credential $Cred -ProvisionVMAgent -EnableAutoUpdate |
Set-AzureRmVMOSDisk -Name $OSDiskName -VhdUri $OSDiskUri -CreateOption FromImage -SourceImageUri $URIofuploadedImage -Windows |
Add-AzureRmVMNetworkInterface -Id $Nic.ID -Primary

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Tag Azure VMs and Resources

Tagging in Azure is a massively useful feature.  I have customers who are interested in identifying resources for billing but they are also a very useful tool for control.  Resources can be grouped by tag and then a script can be used to apply a function to all machines or services with the same tag.

In the example below I call a variable that looks for Azure resources where the type is identified as a Microsoft virtual machine.  Calling this function enables me to extract a range of information. (I fact this script then goes on and uses the ResourceId too)

As referenced in Using tags to organize your Azure resources tags are updated as a whole so if you want to add additional tags you first have to call the existing tags.  In the example below I am adding the new tag to my existing tags.

Finally we are looping this for each vm and applying via a set command.

Hope this is of use to you, happy tagging :-)!


$FindVMs = Find-AzureRmResource | where {$_.ResourceType -like "Microsoft.Compute/virtualMachines"}
$Tags = (Get-AzureRmResource -ResourceId $ResourceId).Tags
$Tags += @{ Owner = "wade" }

Foreach ($vm in $Findvms)
{
$ResourceId = $VM.ResourceId
Set-AzureRmResource -Tag $Tags -ResourceId $ResourceId -Force
}

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Auto Shutdown ASM Virtual Machines in Azure | Azure Automation

I put together a quick script to auto shutdown tagged ARM VMs.

There are many people still running ASM VMs and why wouldn’t you they are still supported (as of 9/2016).

The process is not much different and in fact now Azure Automation enables a RunAs account at set up its much easier to configure.

In the example below I have tacked on changes to the Azure Automation Team’s sample script, one of four created for you when you enable the feature.

<# .DESCRIPTION An example runbook which gets all the Classic VMs in a subscription using the Classic Run As Account (certificate) and then shuts down running VMs .NOTES AUTHOR: Azure Automation Team + Jonathan Wade LASTEDIT: 28-08-2016 #>

$ConnectionAssetName = "AzureClassicRunAsConnection"
$ServiceName = "wadeclassiv01"
	
# Get the connection
$connection = Get-AutomationConnection -Name $connectionAssetName        

# Authenticate to Azure with certificate
Write-Verbose "Get connection asset: $ConnectionAssetName" -Verbose
$Conn = Get-AutomationConnection -Name $ConnectionAssetName
if ($Conn -eq $null)
{
    throw "Could not retrieve connection asset: $ConnectionAssetName. Assure that this asset exists in the Automation account."
}

$CertificateAssetName = $Conn.CertificateAssetName
Write-Verbose "Getting the certificate: $CertificateAssetName" -Verbose
$AzureCert = Get-AutomationCertificate -Name $CertificateAssetName
if ($AzureCert -eq $null)
{
    throw "Could not retrieve certificate asset: $CertificateAssetName. Assure that this asset exists in the Automation account."
}

Write-Verbose "Authenticating to Azure with certificate." -Verbose
Set-AzureSubscription -SubscriptionName $Conn.SubscriptionName -SubscriptionId $Conn.SubscriptionID -Certificate $AzureCert 
Select-AzureSubscription -SubscriptionId $Conn.SubscriptionID

# Get cloud service
    
$VMs = Get-AzureVM -ServiceName $ServiceName

    # Stop each of the started VMs
    foreach ($VM in $VMs)
    {
		if ($VM.PowerState -eq "Stopped")
		{
			# The VM is already stopped, so send notice
			Write-Output ($VM.InstanceName + " is already stopped")
		}
		else
		{
			# The VM needs to be stopped
        	$StopRtn = Stop-AzureVM -Name $VM.Name -ServiceName $VM.ServiceName -Force -ErrorAction Continue

	        if ($StopRtn.OperationStatus -ne 'Succeeded')
	        {
				# The VM failed to stop, so send notice
                Write-Output ($VM.InstanceName + " failed to stop")
	        }
			else
			{
				# The VM stopped, so send notice
				Write-Output ($VM.InstanceName + " has been stopped")
			}
		}
    }


Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

PowerShell to list ASM VMs, Size and CloudService | Azure

I’ve been asked several times now to help customers running IaaS VMs in the Classic mode (ASM Mode) analyse their resources.

The following will list your classic VMs out by CloudService, VMName and VMSize to a CSV file.

You’ll need to edit the location of the file.

Please note this is not meant to be a very sophisticated script just to get you to the answer.

Happy hunting!


Add-AzureAccount
$services = Get-AzureVM | Group-Object -Property ServiceName
foreach ($service in $services)
{
   $out = @()
foreach ($VM in $service.Group)
{ 
$VMSizes = $VM.InstanceSize 

    $props = @{
        Cloudservice = $service.Name        
        VMName = $VM.Name
        VMSizes = $VMSizes
        }
    
    $out += New-Object PsObject -Property $props
}
   $out | Format-Table -AutoSize -Wrap CloudService, VMName, VMSizes
   $out | Export-Csv c:\scripts\test.csv -append
} 
 

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Creating a VM from an Azure Image | Azure

Working with Azure in the enterprise means you will quickly want to create your own custom images.  In this introductory article I will show you an example of how to create an image from an existing generalized imaged.

Please note:

  • This is utilising the ARM model and does not apply to Classic.
  • This assumes you have created a generalized image in Azure and know where it is!
  • This process is not considering on premises VMs.
  • This process uses Windows images.

The following documents and articles were used to create the script below.  Many thanks to the efforts and hard work of the authors.

Create a Virtual Machine from a User Image by Philo

Upload a Windows VM image to Azure for Resource Manager deployments by Cynthia Nottingham

Cynthia shows how to create the image and find the URL of the uploaded image.  She also gives detailed examples of the PowerShell scripts required to create the new VM.

Philo uses variables for existing networks which I found very useful and just comment out the pieces I do not need, e.g. when the vnet already exists.

Happy VM creating!


$cred = Get-Credential
$rgName = "ResourceGroupName"
$location = "Azure Location"
$pipName = "Public IP address Name"
$pip = New-AzureRmPublicIpAddress -Name $pipName -ResourceGroupName $rgName -Location $location -AllocationMethod Dynamic
$subnet1Name = "Subnet Name"
$vnetSubnetAddressPrefix = "Subnet address e.g. 10.1.0.0/24"
$vnetAddressPrefix = "vnet address e.g. 10.1.0.0/16"
$nicname = "Name of Nic"
$vnetName = "Name of vnet"
$subnetconfig = New-AzureRmVirtualNetworkSubnetConfig -Name $subnet1Name -AddressPrefix $vnetSubnetAddressPrefix
#$vnet = New-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName -Location $location -AddressPrefix $vnetAddressPrefix -Subnet $subnetconfig
$nic = New-AzureRmNetworkInterface -Name $nicname -ResourceGroupName $rgName -Location $location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id
$vmName = "Name of VM"
$vmConfig = New-AzureRmVMConfig -VMName $vmName -VMSize "Standard_A4"
$computerName = "Nameof Cumputer"
$vm = Set-AzureRmVMOperatingSystem -VM $vmConfig -Windows -ComputerName $computerName -Credential $cred -ProvisionVMAgent -EnableAutoUpdate
$vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $nic.Id
$osDiskName = "Name of Disk"
$osDiskUri = '{0}vhds/{1}{2}.vhd' -f $storageAcc.PrimaryEndpoints.Blob.ToString(), $vmName.ToLower(), $osDiskName
$urlOfUploadedImageVhd = "URL to generaized image https://somename.blob.core.windows.net/system/Microsoft.Compute/Images/templates/name-osDisk.00aaaa-1bbb-2dd3-4efg-hijlkmn0123.vhd"
$vm = Set-AzureRmVMOSDisk -VM $vm -Name $osDiskName -VhdUri $osDiskUri -CreateOption fromImage -SourceImageUri $urlOfUploadedImageVhd -Windows
$result = New-AzureRmVM -ResourceGroupName $rgName -Location $location -VM $vm
$result

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.