Pete Hinchley: Delegate Hyper-V Permissions using AzMan with PowerShell

In the good old days it was possible to delegate access to Hyper-V using AzMan. Unfortunately, support for AzMan was deprecated with the release of Hyper-V 2012, and nuked entirely in 2012 R2. We are now left with two rather unsavoury options: we can grant god-level access via the Hyper-V Administrators group, or we can use the fine-grained authorisation model offered by Virtual Machine Manager (VMM). I don't find either option inspiring.

Anyway, if you are still living in the past (i.e. Hyper-V 2012 or earlier), and find the need to configure "read only" access to a host using AzMan, the following PowerShell code will do the trick.

The code assumes the existence of an Active Directory group named LAB\hyperv-readers, and should be executed on a Hyper-V host from an elevated PowerShell prompt.

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Interop.Security.AzRoles, Version=2.0.0.0, publicKeyToken=31bf3856ad364e35, culture=neutral")

$store   = "msxml://C:\ProgramData\Microsoft\Windows\Hyper-V\InitialStore.xml"
$readers = "LAB\hyperv-readers"

$azman = New-Object Microsoft.Interop.Security.AzRoles.AzAuthorizationStoreClass
$azman.Initialize(0, $store, $null)

$app = $azman.OpenApplication("Hyper-V Services", $null)

$task = $app.CreateTask("Reader", $null)
$task.IsRoleDefinition = $true
$task.AddOperation("Allow Input to Virtual Machine", $null)
$task.AddOperation("Allow Output from Virtual Machine", $null)
$task.AddOperation("Read Service Configuration", $null)
$task.AddOperation("View External Ethernet Ports", $null)
$task.AddOperation("View Internal Ethernet Ports", $null)
$task.AddOperation("View LAN Endpoints", $null)
$task.AddOperation("View Switch Ports", $null)
$task.AddOperation("View Switches", $null)
$task.AddOperation("View Virtual Machine Configuration", $null)
$task.AddOperation("View Virtual Switch Management Service", $null)
$task.AddOperation("View VLAN Settings", $null)
$task.Submit(0, $null)

[System.Runtime.InteropServices.Marshal]::ReleaseComObject($task) | Out-Null

$role = $app.CreateRole("Reader", $null)
$role.AddRoleDefinition("Reader", $null)
$role.AddMemberName($readers, $null)
$role.Submit(0, $null)

[System.Runtime.InteropServices.Marshal]::ReleaseComObject($role) | Out-Null
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($app) | Out-Null
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($azman) | Out-Null