vSphere permissions: export & import – Part 1

Short security principles intro

One aspect of your vSphere environment that shouldn’t be ignored is the built-in security feature that allows you to control who can do what with which vSphere entity.

Internally this is controlled from the AuthorizationManager. This object contains all the properties and methods you need to configure and manage the built-in security system.

The principle how vSphere entities are protected is quite straightforward.

image

At the basis are the so-called privileges. Each privilege describes a basic action that can be performed on one or more of the vSphere entities.

The vSphere environment doesn’t allow you to assign privileges directly to users or groups. You have to bundle a number of these privileges together in a role.

There are a number of pre-defined roles , such as “No Access” or “Read-Only”. But you can easily create your own roles.

With these roles you can now assign permissions on vSphere entities. You need to select an entity, a principal and a role.

All the above can be done from with the VIC.

Exporting permissions

Last year I added some functions to the VI Toolkit for Windows Community Extensions that revolved around roles and permissions. See the vSphere PowerCLI blog for a short overview of these functions.

In a recent thread on the VMTN PowerCLI community there was a request for a Script to export VC Roles/Permissions/Objects.

Last night there were some tweets from @clinek and @jasonboche that raised the question how these exported permissions could be imported into a new vSphere environment.

An intriguing problem. Let’s tackle it.

First let’s have a look how the script in Script to export VC Roles/Permissions/Objects exported the permissions to a CSV file.

This is an extract of such a CSV file.

roleName objName principalName
VirtualMachinePowerUser Datacenters\DIV\Linux\RH5srv01 myDomain\user1
Admin Datacenters Administrators
Admin Datacenters myDomain\group91
VirtualMachinePowerUser Datacenters\DIV\Linux\RH5srv04_64bit myDomain\user21
VirtualMachineUser Datacenters\DIV\Windows\PCs\XPPC05 myDomain\user08
myDomain Network Admins Datacenters\DIV myDomain\group62

Looks like a regular CSV file, the properties in the first row and the data in the following rows.

In the last row there is a problem. The role “myDomain Network Admins” is not one of the predefined roles.

If we need to import the permission described in the last row into a new vSphere, we will first need to import the customised roles.

In the VI Toolkit for Windows Community Extensions there is a function called Get-TkeRoles that we can use to list all the roles and the privileges they hold.

Luckily the Get-TkeRoles function doesn’t use any PowerShell v2 features, except for the auto-help. That will make it easy to reuse that code in a PowerShell v1 script.

The sole reason for using PowerShell v1 is that we aren’t allowed to run a CTP version in our production environment.

Next problem.

The custom object that represents a permission and the custom object that represents a role do not have the same properties. That makes it difficult to export both objects to the same CSV.

There are a few solutions we can use here:

  1. We can use separate CSV files. One for the roles and one for the permissions
  2. We can define a new custom object that contains all the properties (both of roles and permissions)
  3. We can use a file format, like XML for example, that has no problem with this
    After some consideration the XML format looks the most flexible solution.

Putting all the preceding together our export script becomes:

function Get-Roles
{
  Begin{
    $authMgr = Get-View AuthorizationManager
    $report = @()
  }
  Process{
    foreach($role in $authMgr.roleList){
      $ret = New-Object PSObject
      $ret | Add-Member -Type noteproperty -Name “Name” -Value $role.name
      $ret | Add-Member -Type noteproperty -Name “Label” -Value $role.info.label
      $ret | Add-Member -Type noteproperty -Name “Summary” -Value $role.info.summary
      $ret | Add-Member -Type noteproperty -Name “RoleId” -Value $role.roleId
      $ret | Add-Member -Type noteproperty -Name “System” -Value $role.system
      $ret | Add-Member -Type noteproperty -Name “Privilege” -Value $role.privilege
      $report += $ret
    }
  }
  End{
    return $report
  }
}
function Get-Permissions
{
  Begin{
    $report = @()
    $authMgr = Get-View AuthorizationManager
    $roleHash = @{}
    $authMgr.RoleList | %{
      $roleHash[$_.RoleId] = $_.Name
    }
  }
  Process{
    $perms = $authMgr.RetrieveAllPermissions()
    foreach($perm in $perms){
      $ret = New-Object PSObject
      $entity = Get-View $perm.Entity
      $ret | Add-Member -Type noteproperty -Name “Entity” -Value $entity.Name
      $ret | Add-Member -Type noteproperty -Name “EntityType” -Value $entity.gettype().Name
      $ret | Add-Member -Type noteproperty -Name “Group” -Value $perm.Group
      $ret | Add-Member -Type noteproperty -Name “Principal” -Value $perm.Principal
      $ret | Add-Member -Type noteproperty -Name “Propagate” -Value $perm.Propagate
      $ret | Add-Member -Type noteproperty -Name “Role” -Value $roleHash[$perm.RoleId]
      $report += $ret
    }
  }
  End{
    return $report
  }
}
function New-XmlNode{
  param($node, $nodeName)
  $tmp = $global:vInventory.CreateElement($nodeName)
  $node.AppendChild($tmp)
}
function Set-XmlAttribute{
  param($node, $name, $value)
  $node.SetAttribute($name, $value)
}
function Get-XmlNode{
  param($path)
  $global:vInventory.SelectNodes($path)
}
$vInventory = 



“<Inventory><Roles/><Permissions/></Inventory>”
# Roles
$XMLRoles = Get-XmlNode “Inventory/Roles”
Get-Roles | where {-not $_.System} | % {
  $XMLRole = New-XmlNode $XMLRoles “Role”
  Set-XmlAttribute $XMLRole “Name” $_.Name
  Set-XmlAttribute $XMLRole “Label” $_.Label
  Set-XmlAttribute $XMLRole “Summary” $_.Summary
  $_.Privilege | % {
    $XMLPrivilege = New-XmlNode $XMLRole “Privilege”
    Set-XmlAttribute $XMLPrivilege “Name” $_
  }
}
# Permissions
$XMLPermissions = Get-XmlNode “Inventory/Permissions”
Get-Permissions | % {
  $XMLPerm = New-XmlNode $XMLPermissions “Permission”
  Set-XmlAttribute $XMLPerm “Entity” $_.Entity
  Set-XmlAttribute $XMLPerm “EntityType” $_.EntityType
  Set-XmlAttribute $XMLPerm “Group” $_.Group
  Set-XmlAttribute $XMLPerm “Principal” $_.Principal
  Set-XmlAttribute $XMLPerm “Propagate” $_.Propagate
  Set-XmlAttribute $XMLPerm “Role” $_.Role
}
$vInventory.Save(“C:\vInventory.xml”)

The XML file that comes out of this looks like this.

The Roles branch

roles

And the Permissions branch.

permissions

This concludes part 1 in which we have shown how to export all the required information so that we can later import these permissions in another vSphere environment.

30 thoughts on “vSphere permissions: export & import – Part 1”

  1. That first post didn’t come through right so let me try again…

    [XML]$vInventory = “(Inventory)(Roles/)(Permissions/)(/Inventory)”
    # Roles

    Replace parentheses with chevrons, > and <, and you should be all set.

  2. I was able to get the script working by modifying the vInventory variable’s initial definition:

    [XML]$vInventory = “”
    # Roles

    1. Hi Steve tried your suggestion and when I ran the script my screen filled with red with these messages
      You cannot call a method on a null-valued expression.
      At D:\vmwaresupport\Scripts\Permissions.Export.ps1:58 char:3
      + $node.SetAttribute($name, $value)
      + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      + CategoryInfo : InvalidOperation: (:) [], RuntimeException
      + FullyQualifiedErrorId : InvokeMethodOnNull

  3. Script doesn’t work. I’m getting the same errors as those previously

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Method invocation failed because [System.String] doesn't contain a method named 'Save'.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:88 char:17
    + $vInventory.Save <<<< ("S:\SCRIPTS\vInventory.xml")
    + CategoryInfo : InvalidOperation: (Save:String) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

    tried a couple of the suggestions, they cause different issues.

  4. This looks deceased. #LucD or #Alan can either of you help here? i’m using VMware vSphere PowerCLI 5.1 Release 1 build 793510 for vSphere 5.1 version vCenter and Hypervisor.

    I have modified the original script as advised upon getting same error as described by other mates in this forum.

    Cannot convert value “” to type “System.Xml.XmlDocument”. Error: “Root element is missing.”
    At F:\roles.ps1:64 char:17
    + [XML]$vInventory <<<< = ""
    + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

    You cannot call a method on a null-valued expression.
    At F:\roles.ps1:62 char:26
    + $vInventory.SelectNodes <<<< ($path)
    + CategoryInfo : InvalidOperation: (SelectNodes:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

  5. Using the script here (http://blog.vmote.net/documents/Export-vCenter-Permissions.ps1) I exported all the roles and it seems only some of the permissions. I have vcenter 5.0. For instance under a distributed switch there are port groups that have different permissions. Same with datastores, there are folders with different permissions and datastores inside those folders. And the resource groups do not all have the same permissions. The export text file shows Entity=”New-York” (name of the datacenter) and Entity=”Datacenters”. So I don’t see individual port group, folder, data store or resource pool permissions. Is the script supposed to do this?
    thanks

    Roger

  6. I too get numerous errors regarding calling a method on a null-valued expression.

    just a sample of the numerous errors.

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Method invocation failed because [System.String] doesn't contain a method named 'Save'.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:88 char:17
    + $vInventory.Save <<<< ("S:\SCRIPTS\vInventory.xml")
    + CategoryInfo : InvalidOperation: (Save:String) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

  7. I’m getting the same form of errors as other users.

    The script runs okay, but I get continual errors along the lines of:

    “You cannot call a method on a null-valued expression.
    At C:\tmp\ExportRoles.ps1:85 char:22
    $node.AppendChild( <<<< $tmp)" "You cannot call a method on a null-valued expression. At C:\tmp\ExportRoles.ps1:85 char:23 $node.SetAttribute( <<<< $name, $value)" "You cannot call a method on a null-valued expression. At C:\tmp\ExportRoles.ps1:85 char:44 $tmp = $global:vInventory.CreateElement( <<<< $nodeName)" That loops for a while then I get errors like: "Exception calling "AppendChild" with "1" argument(s): "Object reference not set to an instance of an object." At C:\tmp\ExportRoles.ps1:81 char:22 $node.AppendChild( <<<< $tmp) When carrying out the fix as mentioned by Mitchum, i get the same erros but with a new one thrown in: "Exception calling "CreateElement" with "1" argument(s): "The local name for elements or attributes cannot be null or an empty string." At C:\tmp\ExportRoles.ps1:80 char:37 $tmp = $vInventory.CreateElement( <<<< $nodeName) The script is creating the xml file populated with the descriptors, it's just not populating it with any of my roles or permissions. I'm using vCenter 4.0U1 build 208111 and the PowerCli 4.0.1-208462 Any ideas? "Exception calling "CreateElement" with "1"

  8. Here’s the only part I changed to get it to work, as mentioned by Mitchum:

    ——-
    function Get-XmlNode{
    param($path)
    $vInventory.SelectNodes($path)
    }
    [XML]$vInventory = “”
    # Roles
    ———

  9. Is there an update version of the script that works? I too am getting the same result as everyone else..
    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)

    Guess I just need to learn how to script.. 🙂

    Thanks!

  10. Can someone post the new modified script? I’m getting the same error as everyone else. It looks like Mitchum posted a fix:
    **************************
    There are 2 things to have the script working:
    – Remove the global type for vInventory variable
    – Define the vInventory variable to be a XML object:
    [XML] $vInventory = “”

    Should be ok then
    **************************
    Can someone correct that and re-post?
    Thanks for the help VMware peeps!!

  11. Thanks, Al, for another great script. And thanks Mitchum, that fix worked great.

    One quick question from a newbie, is there any particular application, other than IE, that works well for viewing XML docs? Thanks!

  12. i am running the script with this command – .\EXPORT_vc_roles.ps1 –server vcservername –username username –password “*****”

    and I too get numerous errors regarding calling a method on a null-valued expression.

    just a sample of the numerous errors.

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:58 char:21
    + $node.SetAttribute <<<< ($name, $value)
    + CategoryInfo : InvalidOperation: (SetAttribute:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Method invocation failed because [System.String] doesn't contain a method named 'Save'.
    At S:\SCRIPTS\FID_EXPORT_vc_roles.ps1:88 char:17
    + $vInventory.Save <<<< ("S:\SCRIPTS\vInventory.xml")
    + CategoryInfo : InvalidOperation: (Save:String) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

  13. There are 2 things to have the script working:
    – Remove the global type for vInventory variable
    – Define the vInventory variable to be a XML object:
    [XML] $vInventory = “”

    Should be ok then 😉

  14. Sie können keine Methode für einen Ausdruck mit dem Wert NULL aufrufen.
    Bei D:\permissions\roles.ps1:54 Zeichen:20
    + $node.AppendChild <<<< ($tmp)
    + CategoryInfo : InvalidOperation: (AppendChild:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    I had the same problem. I fixed it by replacing the $global: variables by normal one.

    $vInventory.SelectNodes($path) instead of $global:vInventory.SelectNodes($path)

    And this with all global variables.

  15. @LucD
    This is what I get now. When I run it in the vSphere PowerCLI and when I run it in the powershell v2 CTP3

    Inventory/Roles
    You cannot call a method on a null-valued expression.
    At C:\documents\scripts\POWERCLI\XML_INV.ps1:68 char:33
    + $global:vInventory.SelectNodes <<<< ($path)
    + CategoryInfo : InvalidOperation: (SelectNodes:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    When I run it in the debugger in PowerGUI Script it runs to completion. It is the weirdest thing.

  16. @Christian
    You sure you have the following line copied into the script ?

    $vInventory = [xml]“< Inventory >< Roles/ >< Permissions/ >< /Inventory >”

    It looks as if that variable is not initialised.

    PS: remove the blanks before and after the < and > characters.

  17. @twistedf8
    There must be something wrong with the XMLpath.
    But I’m afraid I can’t reproduce the problem.

    Could you change the Get-XmlNode function like this and send me the output ?

    function Get-XmlNode{
    param($path)

    Write-Host $path
    $global:vInventory.GetEnumerator()

    $global:vInventory.SelectNodes($path)
    }

  18. @LucD I copied the script again and this is the error that I am getting now:
    You cannot call a method on a null-valued expression.
    At C:\documents\scripts\POWERCLI\XML_INV.ps1:62 char:33
    + $global:vInventory.SelectNodes <<<< ($path)
    + CategoryInfo : InvalidOperation: (SelectNodes:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

  19. Strange that you get no error messages whatsoever.
    Some thing I could think of:
    – the account with which you run the script has sufficient authority in the VC
    – you are connected to the VC
    – there is no trap active that captures the possible error messages

    You could include some Write-Host cmdlets at some points in the script to check if the values are actually retrieved.

  20. Once again you have written a script that will be great use to me in my environment and saved me the trouble. However, we I run the script I get only the Node headers in the XML and no errors in the PowerCli interface. Is there something that I could be missing when it comes to running the import script?

  21. Hi Al,
    great Script and (not only this one) a lot for great posts on your site.
    When i run the export-script is get this error messages:
    You cannot call a method on a null-valued expression.
    At \\tsclient\N\Allgemein\VMWare\Scripting\security.ps1:61 char:33
    + $global:vInventory.SelectNodes( <<<< "Inventory/Roles")
    You cannot call a method on a null-valued expression.
    At \\tsclient\N\Allgemein\VMWare\Scripting\security.ps1:53 char:42
    + $tmp = $global:vInventory.CreateElement( <<<< $nodeName)
    You cannot call a method on a null-valued expression.
    At \\tsclient\N\Allgemein\VMWare\Scripting\security.ps1:54 char:20
    + $node.AppendChild( <<<< $tmp)
    You cannot call a method on a null-valued expression.
    At \\tsclient\N\Allgemein\VMWare\Scripting\security.ps1:58 char:21
    + $node.SetAttribute( <<<< $name, $value)
    Do I have to do anything "around" the script ?
    Thanks a lot for you help and thanks a lot for all your other posts !!!!
    Chris

  22. This is a great post about some little features which I just don’t see anyone talking about, and which really shows how mature of product VMware has created. Any chance this exporter would work for 3.5, is all of this new to 4.0? Also may I ask what product you used to view the xml at the end of your post?

Leave a Reply