Public/account.ps1

function New-CSAccount {
    <#
    .SYNOPSIS
        Creates a CloudStack account and its first user.

    .DESCRIPTION
        Wraps the createAccount API. Creates an account in a domain along with an
        initial user built from the mandatory email/name/username/password values.
        The account type controls its privileges (0 = regular user, 1 = root admin,
        2 = domain admin).

    .PARAMETER Email
        Email address of the initial user.

    .PARAMETER FirstName
        First name of the initial user.

    .PARAMETER LastName
        Last name of the initial user.

    .PARAMETER Password
        Password for the initial user. Supply this from a secure source (for example
        a secret store or a decrypted PSCredential) rather than a literal string.

    .PARAMETER UserName
        Login name for the initial user.

    .PARAMETER Account
        Name for the new account. Defaults to the username when omitted.

    .PARAMETER AccountDetails
        Hashtable of extra account detail key/value pairs.

    .PARAMETER AccountId
        Assign a specific account UUID instead of letting CloudStack generate one.

    .PARAMETER AccountType
        Account privilege level: 0 (user), 1 (root admin), or 2 (domain admin).

    .PARAMETER DomainId
        Domain the account belongs to. Defaults to ROOT when omitted.

    .PARAMETER NetworkDomain
        DNS network domain for the account's networks.

    .PARAMETER RoleId
        Dynamic role to assign to the account.

    .PARAMETER Timezone
        Time zone for the initial user (for example 'America/Detroit').

    .PARAMETER UserId
        Assign a specific user UUID to the initial user.

    .EXAMPLE
        New-CSAccount -Email 'ada@example.com' -FirstName 'Ada' -LastName 'Lovelace' -UserName 'ada' -Password 'use-a-secret-store' -Account 'engineering'
        Creates the 'engineering' account with an initial user.

    .EXAMPLE
        New-CSAccount -Email 'ops@example.com' -FirstName 'Ops' -LastName 'Team' -UserName 'ops' -Password $securePasswordPlain -Account 'ops' -DomainId $domainId -AccountType 2 -RoleId $roleId
        Creates a domain-admin account in a specific domain with a dynamic role.
    #>

    [CmdletBinding()]
    param([Parameter(Mandatory=$true)][string]$Email, [Parameter(Mandatory=$true)][string]$FirstName, [Parameter(Mandatory=$true)][string]$LastName, [Parameter(Mandatory=$true)][string]$Password, [Parameter(Mandatory=$true)][string]$UserName, [string]$Account, [hashtable]$AccountDetails, [string]$AccountId, [ValidateSet(0,1,2)][int]$AccountType, [string]$DomainId, [string]$NetworkDomain, [string]$RoleId, [string]$Timezone, [string]$UserId)
    $apiParams = @{ email = $Email; firstname = $FirstName; lastname = $LastName; password = $Password; username = $UserName }
    $parameterMap = @{ Account = 'account'; AccountId = 'accountid'; AccountType = 'accounttype'; DomainId = 'domainid'; NetworkDomain = 'networkdomain'; RoleId = 'roleid'; Timezone = 'timezone'; UserId = 'userid' }
    foreach ($parameter in $parameterMap.Keys) { if ($PSBoundParameters.ContainsKey($parameter)) { $apiParams[$parameterMap[$parameter]] = (Get-Variable -Name $parameter -ValueOnly) } }
    if ($AccountDetails) { foreach ($key in $AccountDetails.Keys) { $apiParams["accountdetails[$key]"] = $AccountDetails[$key] } }
    Invoke-CSApiRequest -Command 'createAccount' -Parameters $apiParams
}

function Remove-CSAccount {
    <#
    .SYNOPSIS
        Deletes an account and its users.

    .DESCRIPTION
        Wraps the deleteAccount API. Permanently removes the account, its users, and
        the resources owned by it. Accepts an account object (or its id) from the
        pipeline. This is destructive, so it honors -WhatIf/-Confirm.

    .PARAMETER AccountId
        The account UUID to delete. Binds from a piped object's Id property.

    .EXAMPLE
        Remove-CSAccount -AccountId 'account-uuid' -Confirm:$false
        Deletes the account without prompting.

    .EXAMPLE
        Get-CSAccount -Name 'obsolete' -DomainId $domainId | Remove-CSAccount
        Pipes an account in and deletes it after confirmation.
    #>

    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
    param([Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)][Alias('Id')][string]$AccountId)
    process {
        if ($PSCmdlet.ShouldProcess("account $AccountId", 'Delete')) { Invoke-CSApiRequest -Command 'deleteAccount' -Parameters @{ id = $AccountId } }
    }
}

function Disable-CSAccount {
    <#
    .SYNOPSIS
        Disables or locks an account.

    .DESCRIPTION
        Wraps the disableAccount API. Identify the account by name (-Account with
        -DomainId) or by -AccountId. Without -Lock the account is disabled (users
        cannot log in or run resources); with -Lock it is locked (login blocked but
        resources keep running). Honors -WhatIf/-Confirm.

    .PARAMETER Account
        Account name. Use with -DomainId.

    .PARAMETER DomainId
        Domain of the named account.

    .PARAMETER AccountId
        The account UUID. Binds from a piped object's Id property.

    .PARAMETER Lock
        Lock the account instead of disabling it.

    .EXAMPLE
        Disable-CSAccount -Account 'engineering' -DomainId 'domain-uuid'
        Disables an account by name.

    .EXAMPLE
        Get-CSAccount -Name 'engineering' -DomainId $domainId | Disable-CSAccount -Lock
        Locks a piped account.
    #>

    [CmdletBinding(SupportsShouldProcess=$true)]
    param([string]$Account, [string]$DomainId, [Parameter(ValueFromPipelineByPropertyName=$true)][Alias('Id')][string]$AccountId, [switch]$Lock)
    process {
        if (-not $PSBoundParameters.ContainsKey('Account') -and -not $PSBoundParameters.ContainsKey('AccountId')) { throw 'Specify Account or AccountId.' }
        $apiParams = @{ lock = $Lock.ToString().ToLowerInvariant() }
        $parameterMap = @{ Account = 'account'; DomainId = 'domainid'; AccountId = 'id' }
        foreach ($parameter in $parameterMap.Keys) { if ($PSBoundParameters.ContainsKey($parameter)) { $apiParams[$parameterMap[$parameter]] = (Get-Variable -Name $parameter -ValueOnly) } }
        $target = if ($PSBoundParameters.ContainsKey('Account')) { $Account } else { $AccountId }
        $action = if ($Lock) { 'Lock' } else { 'Disable' }
        if ($PSCmdlet.ShouldProcess($target, $action)) { Invoke-CSApiRequest -Command 'disableAccount' -Parameters $apiParams }
    }
}

function Enable-CSAccount {
    <#
    .SYNOPSIS
        Enables a disabled or locked account.

    .DESCRIPTION
        Wraps the enableAccount API. Identify the account by name (-Account with
        -DomainId) or by -AccountId. Restores login and resource access for the
        account.

    .PARAMETER Account
        Account name. Use with -DomainId.

    .PARAMETER DomainId
        Domain of the named account.

    .PARAMETER AccountId
        The account UUID. Binds from a piped object's Id property.

    .EXAMPLE
        Enable-CSAccount -Account 'engineering' -DomainId 'domain-uuid'
        Re-enables an account by name.

    .EXAMPLE
        Get-CSAccount -Name 'engineering' -DomainId $domainId | Enable-CSAccount
        Enables a piped account.
    #>

    [CmdletBinding()]
    param([string]$Account, [string]$DomainId, [Parameter(ValueFromPipelineByPropertyName=$true)][Alias('Id')][string]$AccountId)
    process {
        if (-not $PSBoundParameters.ContainsKey('Account') -and -not $PSBoundParameters.ContainsKey('AccountId')) { throw 'Specify Account or AccountId.' }
        $apiParams = @{}; $parameterMap = @{ Account = 'account'; DomainId = 'domainid'; AccountId = 'id' }
        foreach ($parameter in $parameterMap.Keys) { if ($PSBoundParameters.ContainsKey($parameter)) { $apiParams[$parameterMap[$parameter]] = (Get-Variable -Name $parameter -ValueOnly) } }
        Invoke-CSApiRequest -Command 'enableAccount' -Parameters $apiParams
    }
}

function Test-CSAccountOfferingTagPermission {
    <#
    .SYNOPSIS
        Checks whether an account may create offerings with resource tags.

    .DESCRIPTION
        Wraps the isAccountAllowedToCreateOfferingsWithTags API. Returns whether the
        given account is permitted to create service/disk offerings that carry
        resource tags. -AdditionalParameters lets you pass any further API parameters
        verbatim.

    .PARAMETER Account
        Account name to check.

    .PARAMETER DomainId
        Domain of the account.

    .PARAMETER AdditionalParameters
        Hashtable of extra API parameters passed through unchanged.

    .EXAMPLE
        Test-CSAccountOfferingTagPermission -Account 'engineering' -DomainId 'domain-uuid'
        Reports whether the account may tag offerings.
    #>

    [CmdletBinding()]
    param([string]$Account, [string]$DomainId, [hashtable]$AdditionalParameters)
    $apiParams = @{}; if ($PSBoundParameters.ContainsKey('Account')) { $apiParams['account'] = $Account }; if ($PSBoundParameters.ContainsKey('DomainId')) { $apiParams['domainid'] = $DomainId }; if ($AdditionalParameters) { foreach ($key in $AdditionalParameters.Keys) { $apiParams[$key] = $AdditionalParameters[$key] } }
    Invoke-CSApiRequest -Command 'isAccountAllowedToCreateOfferingsWithTags' -Parameters $apiParams
}

function New-CSLdapAccount {
    <#
    .SYNOPSIS
        Creates an account from an LDAP user.

    .DESCRIPTION
        Wraps the ldapCreateAccount API. Provisions a CloudStack account whose
        initial user is imported from the configured LDAP directory, so no password
        is set locally.

    .PARAMETER UserName
        LDAP username to import as the initial user.

    .PARAMETER Account
        Name for the new account. Defaults to the username when omitted.

    .PARAMETER AccountDetails
        Hashtable of extra account detail key/value pairs.

    .PARAMETER AccountId
        Assign a specific account UUID instead of letting CloudStack generate one.

    .PARAMETER AccountType
        Account privilege level: 0 (user), 1 (root admin), or 2 (domain admin).

    .PARAMETER DomainId
        Domain the account belongs to.

    .PARAMETER NetworkDomain
        DNS network domain for the account's networks.

    .PARAMETER RoleId
        Dynamic role to assign to the account.

    .PARAMETER Timezone
        Time zone for the initial user.

    .PARAMETER UserId
        Assign a specific user UUID to the initial user.

    .EXAMPLE
        New-CSLdapAccount -UserName 'ada' -Account 'engineering' -DomainId 'domain-uuid'
        Creates an account from the LDAP user 'ada'.

    .EXAMPLE
        New-CSLdapAccount -UserName 'ops' -Account 'ops' -DomainId $domainId -AccountType 2 -RoleId $roleId
        Imports an LDAP user as a domain-admin account with a role.
    #>

    [CmdletBinding()]
    param([Parameter(Mandatory=$true)][string]$UserName, [string]$Account, [hashtable]$AccountDetails, [string]$AccountId, [ValidateSet(0,1,2)][int]$AccountType, [string]$DomainId, [string]$NetworkDomain, [string]$RoleId, [string]$Timezone, [string]$UserId)
    $apiParams = @{ username = $UserName }; $parameterMap = @{ Account = 'account'; AccountId = 'accountid'; AccountType = 'accounttype'; DomainId = 'domainid'; NetworkDomain = 'networkdomain'; RoleId = 'roleid'; Timezone = 'timezone'; UserId = 'userid' }
    foreach ($parameter in $parameterMap.Keys) { if ($PSBoundParameters.ContainsKey($parameter)) { $apiParams[$parameterMap[$parameter]] = (Get-Variable -Name $parameter -ValueOnly) } }; if ($AccountDetails) { foreach ($key in $AccountDetails.Keys) { $apiParams["accountdetails[$key]"] = $AccountDetails[$key] } }
    Invoke-CSApiRequest -Command 'ldapCreateAccount' -Parameters $apiParams
}

function Set-CSAccountLdapLink {
    <#
    .SYNOPSIS
        Links an account to an LDAP group or organizational unit.

    .DESCRIPTION
        Wraps the linkAccountToLdap API. Associates a CloudStack account with an LDAP
        group (-Type GROUP) or organizational unit (-Type OU) so that matching LDAP
        users can authenticate into the account.

    .PARAMETER Account
        Account name to link.

    .PARAMETER DomainId
        Domain of the account.

    .PARAMETER LdapDomain
        Distinguished name of the LDAP group or OU to link.

    .PARAMETER AccountType
        Privilege level applied to linked users: 0 (user) or 2 (domain admin).

    .PARAMETER Admin
        Username to designate as the account's admin.

    .PARAMETER RoleId
        Dynamic role to assign to linked users.

    .PARAMETER Type
        Whether -LdapDomain is a GROUP or an OU.

    .EXAMPLE
        Set-CSAccountLdapLink -Account 'engineering' -DomainId 'domain-uuid' -LdapDomain 'cn=engineering,ou=groups,dc=example,dc=com'
        Links the account to an LDAP group.

    .EXAMPLE
        Set-CSAccountLdapLink -Account 'engineering' -DomainId $domainId -LdapDomain 'ou=eng,dc=example,dc=com' -Type OU -AccountType 2
        Links the account to an OU with domain-admin privileges.
    #>

    [CmdletBinding()]
    param([Parameter(Mandatory=$true)][string]$Account, [Parameter(Mandatory=$true)][string]$DomainId, [Parameter(Mandatory=$true)][string]$LdapDomain, [ValidateSet(0,2)][int]$AccountType, [string]$Admin, [string]$RoleId, [ValidateSet('GROUP','OU')][string]$Type)
    $apiParams = @{ account = $Account; domainid = $DomainId; ldapdomain = $LdapDomain }; $parameterMap = @{ AccountType = 'accounttype'; Admin = 'admin'; RoleId = 'roleid'; Type = 'type' }
    foreach ($parameter in $parameterMap.Keys) { if ($PSBoundParameters.ContainsKey($parameter)) { $apiParams[$parameterMap[$parameter]] = (Get-Variable -Name $parameter -ValueOnly) } }
    Invoke-CSApiRequest -Command 'linkAccountToLdap' -Parameters $apiParams
}

function Get-CSAccount {
    <#
    .SYNOPSIS
        Lists CloudStack accounts.

    .DESCRIPTION
        Wraps the listAccounts API. Returns accounts filtered by domain, name, id,
        type, state, or tag. Use -ListAll (admin) to include accounts across all
        domains and -IsRecursive to include subdomains. Returns nothing when no
        account matches.

    .PARAMETER AccountType
        Filter by privilege level: 0 (user), 1 (root admin), or 2 (domain admin).

    .PARAMETER Details
        Comma-separated list of detail sections to include in the response.

    .PARAMETER DomainId
        Filter by domain.

    .PARAMETER Id
        Filter by account UUID.

    .PARAMETER IsCleanupRequired
        Filter by whether the account is pending cleanup.

    .PARAMETER IsRecursive
        Include accounts from subdomains of -DomainId.

    .PARAMETER Keyword
        Filter by a keyword substring match on the name.

    .PARAMETER ListAll
        List accounts across all domains the caller can see (admin).

    .PARAMETER Name
        Filter by account name.

    .PARAMETER Page
        Page number for paged results.

    .PARAMETER PageSize
        Number of results per page.

    .PARAMETER ShowIcon
        Include each account's resource icon in the response.

    .PARAMETER State
        Filter by state: enabled, disabled, or locked.

    .PARAMETER Tag
        Filter by a resource tag.

    .EXAMPLE
        Get-CSAccount -DomainId 'domain-uuid' -State enabled -ListAll
        Lists enabled accounts in a domain.

    .EXAMPLE
        Get-CSAccount -Name 'engineering' -DomainId $domainId
        Gets a single account by name and domain.
    #>

    [CmdletBinding()]
    param([ValidateSet(0,1,2)][int]$AccountType, [string]$Details, [string]$DomainId, [string]$Id, [Nullable[bool]]$IsCleanupRequired, [switch]$IsRecursive, [string]$Keyword, [switch]$ListAll, [string]$Name, [int]$Page, [int]$PageSize, [switch]$ShowIcon, [ValidateSet('enabled','disabled','locked')][string]$State, [string]$Tag)
    $apiParams = @{}; $parameterMap = @{ AccountType = 'accounttype'; Details = 'details'; DomainId = 'domainid'; Id = 'id'; Keyword = 'keyword'; Name = 'name'; Page = 'page'; PageSize = 'pagesize'; State = 'state'; Tag = 'tag' }
    foreach ($parameter in $parameterMap.Keys) { if ($PSBoundParameters.ContainsKey($parameter)) { $apiParams[$parameterMap[$parameter]] = (Get-Variable -Name $parameter -ValueOnly) } }; if ($PSBoundParameters.ContainsKey('IsCleanupRequired')) { $apiParams['iscleanuprequired'] = ([bool]$IsCleanupRequired).ToString().ToLowerInvariant() }; if ($IsRecursive) { $apiParams['isrecursive'] = 'true' }; if ($ListAll) { $apiParams['listall'] = 'true' }; if ($ShowIcon) { $apiParams['showicon'] = 'true' }
    $response = Invoke-CSApiRequest -Command 'listAccounts' -Parameters $apiParams
    if ($response.listaccountsresponse.account) { return $response.listaccountsresponse.account }; Write-Verbose 'No accounts found matching the criteria.'
}

function Get-CSSamlAccount {
    <#
    .SYNOPSIS
        Lists or switches a SAML account using CloudStack's SAML login flow.

    .DESCRIPTION
        Wraps the listAndSwitchSamlAccount API. Used during SAML single sign-on to
        enumerate the accounts a federated identity can assume or to switch into one.
        Pass the flow-specific parameters through -AdditionalParameters.

    .PARAMETER AdditionalParameters
        Hashtable of API parameters passed through unchanged (for example account and
        domainid).

    .EXAMPLE
        Get-CSSamlAccount -AdditionalParameters @{ account = 'engineering'; domainid = 'domain-uuid' }
        Switches the SAML session into the named account.
    #>

    [CmdletBinding()]
    param([hashtable]$AdditionalParameters)
    $apiParams = if ($AdditionalParameters) { $AdditionalParameters } else { @{} }
    Invoke-CSApiRequest -Command 'listAndSwitchSamlAccount' -Parameters $apiParams
}

function Lock-CSAccount {
    <#
    .SYNOPSIS
        Locks an account using CloudStack's deprecated lockAccount API.

    .DESCRIPTION
        Wraps the deprecated lockAccount API, which blocks login while leaving the
        account's resources running. Prefer Disable-CSAccount -Lock on current
        CloudStack versions. Honors -WhatIf/-Confirm.

    .PARAMETER Account
        Account name to lock.

    .PARAMETER DomainId
        Domain of the account.

    .EXAMPLE
        Lock-CSAccount -Account 'engineering' -DomainId 'domain-uuid'
        Locks the account by name.
    #>

    [CmdletBinding(SupportsShouldProcess=$true)]
    param([Parameter(Mandatory=$true)][string]$Account, [Parameter(Mandatory=$true)][string]$DomainId)
    if ($PSCmdlet.ShouldProcess($Account, 'Lock')) { Invoke-CSApiRequest -Command 'lockAccount' -Parameters @{ account = $Account; domainid = $DomainId } }
}

function Set-CSAccountDefaultZone {
    <#
    .SYNOPSIS
        Marks a default zone for an account.

    .DESCRIPTION
        Wraps the markDefaultZoneForAccount API. Sets the zone that new resources for
        the account default to.

    .PARAMETER Account
        Account name.

    .PARAMETER DomainId
        Domain of the account.

    .PARAMETER ZoneId
        Zone to set as the account's default.

    .EXAMPLE
        Set-CSAccountDefaultZone -Account 'engineering' -DomainId 'domain-uuid' -ZoneId 'zone-uuid'
        Makes the given zone the account's default.
    #>

    [CmdletBinding()]
    param([Parameter(Mandatory=$true)][string]$Account, [Parameter(Mandatory=$true)][string]$DomainId, [Parameter(Mandatory=$true)][string]$ZoneId)
    Invoke-CSApiRequest -Command 'markDefaultZoneForAccount' -Parameters @{ account = $Account; domainid = $DomainId; zoneid = $ZoneId }
}

function Set-CSAccount {
    <#
    .SYNOPSIS
        Updates an account.

    .DESCRIPTION
        Wraps the updateAccount API. Identify the account by name (-Account with
        -DomainId) or by -AccountId, then change its name (-NewName), network domain,
        role, or details. Accepts an account object (or its id) from the pipeline.

    .PARAMETER Account
        Account name. Use with -DomainId.

    .PARAMETER AccountDetails
        Hashtable of account detail key/value pairs to set.

    .PARAMETER DomainId
        Domain of the named account.

    .PARAMETER AccountId
        The account UUID. Binds from a piped object's Id property.

    .PARAMETER NetworkDomain
        New DNS network domain for the account.

    .PARAMETER NewName
        New name for the account.

    .PARAMETER RoleId
        New dynamic role for the account.

    .EXAMPLE
        Set-CSAccount -Account 'engineering' -DomainId 'domain-uuid' -NewName 'platform-engineering'
        Renames an account.

    .EXAMPLE
        Get-CSAccount -Name 'engineering' -DomainId $domainId | Set-CSAccount -RoleId $roleId
        Reassigns a piped account's role.
    #>

    [CmdletBinding()]
    param([string]$Account, [hashtable]$AccountDetails, [string]$DomainId, [Parameter(ValueFromPipelineByPropertyName=$true)][Alias('Id')][string]$AccountId, [string]$NetworkDomain, [string]$NewName, [string]$RoleId)
    process {
        if (-not $PSBoundParameters.ContainsKey('Account') -and -not $PSBoundParameters.ContainsKey('AccountId')) { throw 'Specify Account or AccountId.' }
        $apiParams = @{}; $parameterMap = @{ Account = 'account'; DomainId = 'domainid'; AccountId = 'id'; NetworkDomain = 'networkdomain'; NewName = 'newname'; RoleId = 'roleid' }
        foreach ($parameter in $parameterMap.Keys) { if ($PSBoundParameters.ContainsKey($parameter)) { $apiParams[$parameterMap[$parameter]] = (Get-Variable -Name $parameter -ValueOnly) } }; if ($AccountDetails) { foreach ($key in $AccountDetails.Keys) { $apiParams["accountdetails[$key]"] = $AccountDetails[$key] } }
        Invoke-CSApiRequest -Command 'updateAccount' -Parameters $apiParams
    }
}