Your vSphere environment is a living environment. Inventory objects are created and removed all the time. Together with these inventory objects there are often security permissions that come along. Team X needs Power User access for all VMs in folder Project-X. But the life-cycle management of these permissions is often not as fluent as your VM life cycle management. There is no built in permission cleanup method.
As a result, old permissions might be left behind, and what is worse, redundant permissions might be present. This doesn’t make the task of investigating “Who can do what?” in your vSphere environment any easier.
With the help of the function in this post you can now get rid of all these redundant permissions!
The Script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
function Optimize-VIPermission{ <# .SYNOPSIS Find and remove redundant permissions on vSphere objects .DESCRIPTION The function will recursively scan the permissions on the inventory objects passed via the Entity parameter. Redundant permissions will be removed. .NOTES Author: Luc Dekens .PARAMETER Entity One or more vSphere inventory objects from where the scan shall start .EXAMPLE PS> Optimize-Permission -Entity Folder1 -WhatIf .EXAMPLE PS> Optimize-Permission -Entity Folder? .EXAMPLE PS> Get-Folder -Name Folder* | Optimize-Permission #> [cmdletbinding(SupportsShouldProcess=$true)] param( [parameter(ValueFromPipeline)] [PSObject[]]$Entity ) Begin{ function Optimize-iVIPermission{ [cmdletbinding(SupportsShouldProcess=$true)] param( [parameter(ValueFromPipeline)] [VMware.Vim.ManagedObjectReference]$Entity, [VMware.Vim.Permission[]]$Permission = $null ) Process{ $entityObj = Get-View -Id $Entity $removePermission = @() $newParentPermission = @() if($Permission){ foreach($currentPermission in $entityObj.Permission){ foreach($parentPermission in $Permission){ if($parentPermission.Principal -eq $currentPermission.Principal -and $parentPermission.RoleId -eq $currentPermission.RoleId){ $removePermission += $currentPermission break } else{ $newParentPermission += $currentPermission } } } } else{ $newParentPermission += $entityObj.Permission } if($removePermission){ if($pscmdlet.ShouldProcess("$($entityObj.Name)", "Cleaning up permissions")){ $removePermission | %{ $authMgr.RemoveEntityPermission($Entity,$_.Principal,$_.Group) } } } $Permission += $newParentPermission if($entityObj.ChildEntity){ $entityObj.ChildEntity | Optimize-iVIPermission -Permission $Permission } } } } Process{ foreach($entry in $Entity){ if($entry -is [System.String]){ $entry = Get-Inventory -Name $entry } Optimize-iVIPermission -Entity $entry.ExtensionData.MoRef } } } |
Annotations
Line 24-25: the function accepts one or more vSphere Inventory objects, as a parameter or through the pipeline
Line 29-70: this is the internal function that does the actual work. The main function is just a wrapper to handle (and eventually convert) the parameter.
Line 39-40: the function recursively descends the inventory tree, and it checks the permissions on each node against the recursive permissions that were assigned in nodes higher up in the tree. To check what is there and what can be removed, the arrays $removePermission and $newParentPermission are used.
Line 44-45: in the current version of the function, the Principal and the Role need to be match, before the permission is considered to be removed
Line 58-64: if redundant permissions were discovered on the current node in the vSphere inventory tree, then the redundant permission will be removed. Or if the WhatIf switch was used, a message will be displayed.
Line 68: the internal function is called recursively for each child of the current node. The permissions that were already encountered on the parent nodes, are passed as a parameter to the internal function.
Line 77-79: a “cheap” implementation of OBN
Sample Usage
The use of the Optimize-VIPermission function is quite straightforward.
As a test environment, we applied some permissions on two different node in the tree. In this case for the Principal LOCAL\test.
In its simplest form, you just pass the name of the object where the optimization should start. Notice how we used the WhatIf switch on the function call. No actual permissions will be removed, but the function will show what it would do.
1 |
Optimize-VIPermission -Entity Test1 -WhatIf |
And this produces the following output.
The function also accepts multiple starting points, you can pass multiple locations on the Entity parameter.
1 |
Optimize-VIPermission -Entity Test1,Test2 -WhatIf |
The function output now shows the following (because we added a second redundant permission in the tree under Test2).
And you can use the function in a pipeline construct, like this.
1 |
Get-Folder -Name Test? | Optimize-VIPermission -WhatIf |
Which produces exactly the same output as the previous example.
Note: it is strongly advised to always run this first with the WhatIf switch. Only when the WhatIf switch is not used, or when it receives a $false value, will the redundant permissions actually be removed!
Enjoy!