vSphere permissions: export & import – Part 2

In Part1 of this article we had all the roles and permissions exported to an XML file. It’s now time to import the roles and permissions into a Virtual Center.

The script does in fact the reverse of what the script in Part 1 did.

But there were a few “gotchas“ that had to be solved before arriving at a working solution.

Duplicate Names

The script does not take into account that you can have different objects in your vSphere environment with the same name! Which imho is not a good practice in any case.

Should someone have the need for this functionality let me know and I will try to adapt the scripts.

Principals

The script does not create the principals that are mentioned in the XML file. If these principals do not exists in the environment where you want to import the roles and permissions the script will show errors.

Speed of execution

The permissions are set with an API called SetEntityPermissions.

As can be seen in the API Reference Guide this method requires a Managed Object Reference (MoRef) to a ManagedEntity. A ManagedEntity object is the parent object of most of the managed objects in vSphere.

This way of working avoids that there would have to be a separate method for each of the derived managed objects.

In the XML we have the name of the vSphere entity in property $_.Entity. We could get at the required ManagedEntity MoRef like this:

001
(Get-Inventory -Name $_.Entity | Get-View).MoRef

But if you run this you will notice that this is in fact quite slow. If you need to import hundreds of permissions the script would run for hours.

After some trial and error the following turned out to be the fastest method (see line 62 in the script below).

  • Use the Get-View cmdlet. It’s a lot faster. See also PowerCLPowerCLI on steroids – Custom attributes.
  • The Get-View cmdlet, in this format, requires the type of object (-ViewType) to be passed. We can solve this requirement by adding the EntityType attribute to the Permission node.
  • We use the -Filter parameter of the Get-View cmdlet to get only the object we want. But watch out with this filter! See the next section for more details.

Get-View filter and regular expressions

As it turns out the –Filter parameter interprets the “value” as a regular expression!

That means that if you have vSphere objects whose name accidently contains one or more [regex] meta-character, the –Filter won’t return the object.

As an example, suppose you have a VirtualMachine with a name of “MyPC (v1)”, which is by the way a valid guest name. When you do the following:

001
$pc = Get-View -ViewType VirtualMachine -Filter @{“Name”=“MyPC (v1)”}

The Get-View cmdlet will not return the VirtualMachine object as you would expect.

The solution is to “escape” all the regex meta-characters in the value. Something like this

001
$pc = Get-View -ViewType VirtualMachine -Filter @{“Name”=“MyPC \(v1\)”}

To solve the occurrence of regex meta-characters in the script the lines 58..60 were added.

Note: these aren’t all the regex meta-characters! Depending on your environment and the object names you used you will have to update these lines!

“True”  is not $true

In the Permission nodes there are two attributes that represent a Boolean value. But when you access these attribute values you will notice that they are text representations (strings) of the actual Boolean values.

In the Permission object we need to pass two Boolean values.

So we have to convert the node attribute values from strings to Booleans.

This can be done like this:

001
$perm.Group = &{if($_.Group -eq “true”) {$true} else {$false}}

The import script

Below the actual script that will recreate all custom roles and set all permissions as defined in the XML file.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
function New-Role
{
param($name, $privIds)
Begin{}
Process{
$roleId = $authMgr.AddAuthorizationRole($name,$privIds)
}
End{
return $roleId
}
}
function Set-Permission
{
param(
[VMware.Vim.ManagedEntity]$object,
[VMware.Vim.Permission]$permission
)
Begin{}
Process{
$perms = $authMgr.SetEntityPermissions($object.MoRef,@($permission))
}
End{
return
}
}

# Create hash table with the current roles
$authMgr = Get-View AuthorizationManager
$roleHash = @{}
$authMgr.RoleList | % {
$roleHash[$_.Name] = $_.RoleId
}
# Read XML file
$XMLfile = “C:\vInventory.xml”
$vInventory = “<dummy/>”
$vInventory.Load($XMLfile)
# Define Xpaths for the roles and the permissions
$XpathRoles = “Inventory/Roles/Role”
$XpathPermissions = “Inventory/Permissions/Permission”
# Create custom roles
$vInventory.SelectNodes($XpathRoles) | % {
if(-not $roleHash.ContainsKey($_.Name)){
$privArray = @()
$_.Privilege | % {
$privArray += $_.Name
}
$roleHash[$_.Name] = (New-Role $_.Name $privArray)
}
}
# Set permissions
$vInventory.SelectNodes($XpathPermissions) | % {
$perm = New-Object VMware.Vim.Permission
$perm.group = &{if ($_.Group -eq “true”) {$true} else {$false}}
$perm.principal = $_.Principal
$perm.propagate = &{if($_.Propagate -eq “true”) {$true} else {$false}}
$perm.roleId = $roleHash[$_.Role]

$EntityName = $_.Entity.Replace(“(“,“\(“).Replace(“)”,“\)”)
$EntityName = $EntityName.Replace(“[“,“\[“).Replace(“]”,“\]”)
$EntityName = $EntityName.Replace(“{“,“\{“).Replace(“}”,“\}”)

$entity = Get-View -ViewType $_.EntityType -Filter @{“Name”=$EntityName}

Set-Permission $entity $perm
}

Since it was impractical (and even impossible) to test the script in all possible environments I would strongly advise to test the script thoroughly before using it in your production environment !

Technorati Tags: ,,,

12 thoughts on “vSphere permissions: export & import – Part 2”

  1. Do you have an updated script to work with duplicate object names or more specifically folder names? Does this script require v2.0? I’m getting a few errors:
    Index operation failed; the array index evaluated to null at $roleHash[$_.Name] = $_.RoleId

    Method invocation failed because [System.Object[]] doesn’t contain a method named ‘AddAuthorizationRole’.

  2. That makes sense now why LucD’s suggestion didn’t work for me. The forum is dropping out the dummy variable in my line. Here it is with underscores…
    $vInventory =“__”

  3. Changing line 35 to “$vInventory =“”” worked for me. All custom roles are added properly except for the last one. I get the same error that Rj.Aguilera gets. I’ll just add that one manually for now.

  4. Hey LucD – Thanks for the Export/Import script. This will prove very useful for me in my upgrade from vCenter 2.5 to 4.1. I’m testing it in my lab environment and I’m getting an error on the import. ( I got your fixed export script on the VMware forums.)
    I updated line 35 as mentioned above and I’m getting the error below.

    Any help you can provide is appreciated!
    ———————-

    Cannot convert value “” to type “System.Xml.XmlDocument”. Error: “Root element is missing.”

    At C:\VM_permissions_import.ps1:36 char:17
    + [XML]$vInventory <<<< = ""
    + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMet
    adataException
    + FullyQualifiedErrorId : RuntimeException

  5. Nice work again Alan,

    I’m stealing some snippets of this to periodically re-create roles in my test environment from prod.

    I did encounter the same errors as Simon… So I opted to use a different method of setting up the xml template.

    function create-XMLTemplate([String]$XMLTemplateFile)
    {
    $input | Out-File $XMLTemplateFile -encoding UTF8
    }

    $vInventory = New-Object XML
    $vInventoryData = @”@
    $vInventoryData | create-XMLTemplate $rolesReportLocation
    $vInventory.load($rolesReportLocation)

    Thanks for saving me some time… again 🙂
    Doug

  6. Nice work again Alan,

    I’m stealing some snippets of this to periodically re-create roles in my test environment from prod.

    Thanks for saving me some time… again 🙂
    Doug

  7. Hi. Great job LucD!

    I get this error

    Exception calling “SetEntityPermissions” with “2” argument(s): “entity”
    At C:\Users\A\AppData\Local\Temp\2\116fb4a3-242b-4d1f-814d-9b8278aeabc3.p
    s1:54 char:43
    + $perms = $authMgr.SetEntityPermissions <<<< ($object.MoRef,@($permission)
    )
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

  8. Hi Luc, I now get this error:

    Cannot convert value “[/xml]” to type “System.Xml.XmlDocument”. Error: “Data at the root level is invalid. Line 1, position 1.”
    At :line:36 char:11
    + $vInventory <<<< = "[/xml]"

  9. Hi Alan, I’m trying to run this import script and I am getting the following error:

    Exception calling “AddAuthorizationRole” with “2” argument(s): “A specified parameter was not correct.
    privIds”
    At :line:8 char:39
    + $roleId = $authMgr.AddAuthorizationRole <<<< ($name,$privIds)

    Any idea?

    Simon

  10. Iam getting the following error on inport. Any ideas?

    [vSphere PowerCLI] C:\Program Files\VMware\Infrastructure\vSphere PowerCLI> $vIn
    ventory.Load($XMLfile)
    Method invocation failed because [System.String] doesn’t contain a method named
    ‘Load’.
    At line:1 char:17
    + $vInventory.Load <<<< ($XMLfile)
    + CategoryInfo : InvalidOperation: (Load:String) [], RuntimeExcep
    tion
    + FullyQualifiedErrorId : MethodNotFound

Leave a Reply