PSDuo.psm1

#Region './Private/ConvertFrom-Epoch.ps1' -1


Function ConvertFrom-Epoch {
    <#
        .SYNOPSIS
        Converts epoch to Datetime.

        .DESCRIPTION
        Converts epoch to Datetime.

        .PARAMETER Date
        Specifies the epoch time.

        .EXAMPLE
        PS> ConvertFrom-Epoch -Date 1623819273890

    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [int64]$Date

    )
    process {
        if ($($Date.tostring().length) -gt 10 )
        {
            return (Get-Date -Date "01/01/1970").AddMilliseconds($($Date))
        }
        else
        {
            return (Get-Date -Date "01/01/1970").AddSeconds($($Date))
        }
    }
}
#EndRegion './Private/ConvertFrom-Epoch.ps1' 34
#Region './Private/ConvertTo-Base64.ps1' -1

function ConvertTo-Base64 {
    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateScript({Test-Path $_})]
        [string]$Path,
        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$String
    )
    Begin {
        [array]$Output = @()
    }
    Process {
        if($PSBoundParameters.ContainsKey("Path"))
        {
            $Output += [pscustomobject]@{
                Input = $Path
                B64Encoded = [convert]::ToBase64String((Get-Content $Path -Encoding byte))
            }
        }
        if($PSBoundParameters.ContainsKey("String"))
        {
            $Output += [pscustomobject]@{
                Input = $String
                B64Encoded = [convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("$($String)"))
            }
        }

    }
    End {
        return $Output
    }
}
#EndRegion './Private/ConvertTo-Base64.ps1' 34
#Region './Private/ConvertTo-Epoch.ps1' -1

Function ConvertTo-Epoch {
    <#
        .SYNOPSIS
        Converts Datetime to epoch.

        .DESCRIPTION
        Converts Datetime to epoch.

        .PARAMETER Date
        Specifies the Date time "mm/dd/yyyy hh:mm".

        .EXAMPLE
        PS> ConvertTo-Epoch -Date $(Get-Date)

        .EXAMPLE
        PS> $date = (Get-Date).AddDays(-30)
        PS> ConvertTo-Epoch -Date $date
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [ValidateNotNullOrEmpty()]
        [System.DateTime]$Date,
        [switch]$Milliseconds
    )
    Process {
        $Date=$Date -f "mm/dd/yyyy hh:mm"

        $output = (New-TimeSpan -Start (Get-Date -Date "01/01/1970") -End $Date)
        if($PSBoundParameters.ContainsKey("Milliseconds"))
        {
            return $output.TotalMilliseconds
        }
        return $output.TotalSeconds
    }
}
#EndRegion './Private/ConvertTo-Epoch.ps1' 37
#Region './Private/Invoke-DuoApi.ps1' -1

# This function is based on https://github.com/PWSHNinja/PSDuo/blob/master/PSDuo/private/Convertto-DUORequest.ps1
function Invoke-DuoApi {
    [cmdletbinding()]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$ApiPath,

        [Parameter(Mandatory = $false)]
        [hashtable]$ApiParams,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [ValidateSet("GET","POST","PATCH","PUT","DELETE")]
        [string]$Method,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [pscredential]$Credential,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [String]$ApiHostname
    )
    Process {
        #Decrypt our keys from our config
        $skey = "$($Credential.GetNetworkCredential().Password)"
        $iKey = "$($Credential.UserName)"
        $apiHost = $ApiHostname
        $Date = (Get-Date).ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss -0000")
        [array]$Output = @()

        #Stringified Params/URI Safe chars - I think this should grab everything...
        if($PSBoundParameters.ContainsKey("ApiParams")) {
            $StringAPIParams = ($ApiParams.Keys | Sort-Object | ForEach-Object {
                $_ + "=" + [uri]::EscapeDataString($ApiParams.$_)
            }) -join "&"
        }

        #DUO Params formatted and stored as bytes with StringAPIParams
        $DuoParams = (@(
            $Date.Trim(),
            $method.ToUpper().Trim(),
            $apiHost.ToLower().Trim(),
            $ApiPath.Trim(),
            $StringAPIParams.trim()
        ).trim() -join "`n").ToCharArray().ToByte([System.IFormatProvider]$UTF8)

        #Hash out some secrets
        $HMACSHA1 = [System.Security.Cryptography.HMACSHA1]::new($skey.ToCharArray().ToByte([System.IFormatProvider]$UTF8))
        $hmacsha1.ComputeHash($DuoParams) | Out-Null
        $ASCII = [System.BitConverter]::ToString($hmacsha1.Hash).Replace("-", "").ToLower()

        #Create the new header and combing it with our iKey to use it as Authentication
        $AuthHeadder = $ikey + ":" + $ASCII
        [byte[]]$ASCIBytes = [System.Text.Encoding]::ASCII.GetBytes($AuthHeadder)

        #Create our Parameters for the webrequest - Easy @Splatting!

        $DUOWebRequestParams = @{
            URI = "https://$($apiHost)$($ApiPath)?$($StringAPIParams.trim())"
            Headers     = @{
                "X-Duo-Date"    = $Date
                "Authorization" = ('Basic {0}' -f [System.Convert]::ToBase64String($ASCIBytes))
            }
            Method      = $method
            ContentType = 'application/x-www-form-urlencoded'
            # ErrorAction = 'Stop'
        }

        try{
            $Output = Invoke-RestMethod @DUOWebRequestParams
        }
        catch {
            throw $PSItem
        }

    }
    End {
        return $Output
    }
}

#EndRegion './Private/Invoke-DuoApi.ps1' 84
#Region './Public/Add-DuoAdministrativeUnitMember.ps1' -1

function Add-DuoAdministrativeUnitMember {
    <#
    .SYNOPSIS
    Add member to administrative unit

    .DESCRIPTION
    Add member to administrative unit

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER AdministrativeUnitId
    Target administrative unit ID

    .PARAMETER AdministratorId
    target administrator ID

    .PARAMETER GroupId
    target group ID

    .PARAMETER IntegrationKey
    Target integration key

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Add-DuoAdministrativeUnitMember -ApiHostname $ApiHostname -Credential $Credential -GroupId '0AUSF8DF9A7S6DF98AS' -AdministrativeUnitId 'AJ0SDF8ASU0DF8'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High", DefaultParameterSetName = "A")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="A")]
        [Parameter(ParameterSetName="B")]
        [Parameter(ParameterSetName="C")]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="A")]
        [Parameter(ParameterSetName="B")]
        [Parameter(ParameterSetName="C")]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="A")]
        [Parameter(ParameterSetName="B")]
        [Parameter(ParameterSetName="C")]
        [string]$AdministrativeUnitId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="A")]
        [Parameter(ParameterSetName="B")]
        [Parameter(ParameterSetName="C")]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="A")]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="B")]
        [string]$GroupId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="C")]
        [string]$IntegrationKey
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Add member to admin unit"))
        {

            switch ($PSCmdlet.ParameterSetName) {
                "A" {[string]$apiPath = "/admin/v1/administrative_units/$($AdministrativeUnitId)/admin/$($AdministratorId)"}
                "B" {[string]$apiPath = "/admin/v1/administrative_units/$($AdministrativeUnitId)/group/$($GroupId)"}
                "C" {[string]$apiPath = "/admin/v1/administrative_units/$($AdministrativeUnitId)/integration/$($IntegrationKey)"}
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Add-DuoAdministrativeUnitMember.ps1' 104
#Region './Public/Add-DuoHardwareTokenToUser.ps1' -1

function Add-DuoHardwareTokenToUser {
    <#
    .SYNOPSIS
    Associate a token with the user

    .DESCRIPTION
    Associate a token with the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .PARAMETER TokenId
    Target token ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Add-DuoHardwareTokenToUser -ApiHostname $ApiHostname -Credential $Credential -UserId '0AUSF8DF9A7S6DF98AS' -TokenId 'AJ0SDF8ASU0DF8' -AccountId 'SD0AF870ADSF70ASG'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$TokenId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Add token to user"))
        {
            [string]$apiPath = "/admin/v1/users/$($UserId)/tokens"
            if($PSBoundParameters.ContainsKey("TokenId"))
            {
                $parameter["token_id"] = "$($TokenId)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Add-DuoHardwareTokenToUser.ps1' 76
#Region './Public/Add-DuoPhoneToUser.ps1' -1

function Add-DuoPhoneToUser {
    <#
    .SYNOPSIS
    Associate a phone with the user

    .DESCRIPTION
    Associate a phone with the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .PARAMETER PhoneId
    Target Phone ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Add-DuoPhoneToUser -ApiHostname $ApiHostname -Credential $Credential -UserId '0AUSF8DF9A7S6DF98AS' -PhoneId 'AJ0SDF8ASU0DF8' -AccountId 'SD0AF870ADSF70ASG'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$PhoneId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Add phone to user"))
        {
            [string]$apiPath = "/admin/v1/users/$($UserId)/phones"
            if($PSBoundParameters.ContainsKey("PhoneId"))
            {
                $parameter["phone_id"] = "$($PhoneId)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Add-DuoPhoneToUser.ps1' 76
#Region './Public/Add-DuoUserToGroup.ps1' -1

function Add-DuoUserToGroup {
    <#
    .SYNOPSIS
    Associate a group with the user

    .DESCRIPTION
    Associate a group with the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .PARAMETER GroupId
    Target Group ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Add-DuoUserToGroup -ApiHostname $ApiHostname -Credential $Credential -UserId '0AUSF8DF9A7S6DF98AS' -GroupId 'AJ0SDF8ASU0DF8' -AccountId 'SD0AF870ADSF70ASG'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$GroupId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Add user to group"))
        {
            [string]$apiPath = "/admin/v1/users/$($UserId)/groups"
            if($PSBoundParameters.ContainsKey("GroupId"))
            {
                $parameter["group_id"] = "$($GroupId)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Add-DuoUserToGroup.ps1' 76
#Region './Public/Clear-DuoAdministratorExpiration.ps1' -1

function Clear-DuoAdministratorExpiration {
    <#
    .SYNOPSIS
    Clear expiration for the administrator after the admin has been expired due to inactivity.
    The administrator's status changes from "Expired" to the status applied to that admin before inactive expiration, and restores access to the Duo Admin Panel if the effective status is "Active"

    .DESCRIPTION
    Clear expiration for the administrator after the admin has been expired due to inactivity.
    The administrator's status changes from "Expired" to the status applied to that admin before inactive expiration, and restores access to the Duo Admin Panel if the effective status is "Active"

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER AdministratorId
    Target Administrator ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Clear-DuoAdministratorExpiration -ApiHostname $ApiHostname -AdministratorId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($AdministratorId, "Clear expiration for the administrator"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)/clear_inactivity"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Clear-DuoAdministratorExpiration.ps1' 67
#Region './Public/Get-DuoAccount.ps1' -1

function Get-DuoAccount {
    <#
    .SYNOPSIS
    Returns a list of Child accounts.

    .DESCRIPTION
    Returns a list of Child accounts

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAccount -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/accounts/v1/account/list'
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoAccount.ps1' 46
#Region './Public/Get-DuoAccountInfo.ps1' -1

function Get-DuoAccountInfo {
    <#
    .SYNOPSIS
    Returns a summary of account utilization information.

    .DESCRIPTION
    Returns a summary of account utilization information

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAccountInfo -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/info/summary'
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoAccountInfo.ps1' 56
#Region './Public/Get-DuoAdministrativeUnit.ps1' -1

function Get-DuoAdministrativeUnit {
    <#
    .SYNOPSIS
    Returns a paged list of all administrative units if no parameters specified.

    .DESCRIPTION
    Returns a paged list of all administrative units if no parameters specified

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER GroupId
    Target group. When specified returns information about the group

    .PARAMETER AdministratorId
    Target administrator ID

    .PARAMETER IntegrationKey
    Target integration id

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAdministrativeUnit -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$GroupId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministrativeUnitId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$IntegrationKey
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/administrative_units'
        if($PSBoundParameters.ContainsKey("AdministrativeUnitId"))
        {
            [string]$apiPath = "/admin/v1/administrative_units/$($AdministrativeUnitId)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        if($PSBoundParameters.ContainsKey("GroupId"))
        {
            $parameter["group_id"] = $GroupId
        }
        if($PSBoundParameters.ContainsKey("IntegrationKey"))
        {
            $parameter["integration_key"] = $IntegrationKey
        }
        if($PSBoundParameters.ContainsKey("AdministratorId"))
        {
            $parameter["admin_id"] = $AdministratorId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoAdministrativeUnit.ps1' 93
#Region './Public/Get-DuoAdministrator.ps1' -1

function Get-DuoAdministrator {
    <#
    .SYNOPSIS
    Returns a list of Administrators.

    .DESCRIPTION
    Returns a list of Administrators

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER AdministratorId
    Target Admin Id

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAdministrator -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/admins'
        if($PSBoundParameters.ContainsKey("AdministratorId"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoAdministrator.ps1' 66
#Region './Public/Get-DuoAdministratorAuthMethod.ps1' -1

function Get-DuoAdministratorAuthMethod {
    <#
    .SYNOPSIS
    Retrieve a list of the secondary authentication methods permitted for administrator log on to the Duo Admin Panel

    .DESCRIPTION
    Retrieve a list of the secondary authentication methods permitted for administrator log on to the Duo Admin Panel

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.


    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAdministratorAuthMethod -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/admins/password_mgmt'
        if($PSBoundParameters.ContainsKey("AdministratorId"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)/password_mgmt"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoAdministratorAuthMethod.ps1' 61
#Region './Public/Get-DuoAdministratorExternalPasswordStatus.ps1' -1

function Get-DuoAdministratorExternalPasswordStatus {
    <#
    .SYNOPSIS
    Returns a list of Administrators indicating whether they have been configured for external password management

    .DESCRIPTION
    Returns a list of Administrators indicating whether they have been configured for external password management

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER AdministratorId
    Target Admin Id

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAdministratorExternalPasswordStatus -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/admins/password_mgmt'
        if($PSBoundParameters.ContainsKey("AdministratorId"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)/password_mgmt"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoAdministratorExternalPasswordStatus.ps1' 66
#Region './Public/Get-DuoAdministratorLog.ps1' -1

function Get-DuoAdministratorLog {
    <#
    .SYNOPSIS
    Returns a list of administrator log events..

    .DESCRIPTION
    Returns a list of administrator log events.

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER StartDate
    Start date in powershell notation $(Get-Date).AddDays(-30)

.EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAdministratorLog -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAdministratorLog -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -StartDate $(Get-Date).AddDays(-30)
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [datetime]$StartDate
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/logs/administrator'
        if($PSBoundParameters.datetime("StartDate"))
        {
            mintime = $(ConvertTo-Epoch -Date $StartDate)
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoAdministratorLog.ps1' 71
#Region './Public/Get-DuoAdministratorPendingActivation.ps1' -1

function Get-DuoAdministratorPendingActivation {
    <#
    .SYNOPSIS
    Returns a paged list of pending administrator activations.

    .DESCRIPTION
    Returns a paged list of pending administrator activations.

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAdministratorPendingActivation -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/admins/activations'
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoAdministratorPendingActivation.ps1' 56
#Region './Public/Get-DuoAuthenticationAttemptsReport.ps1' -1

function Get-DuoAuthenticationAttemptsReport {
    <#
    .SYNOPSIS
    Retrieve counts of authentication attempts for a given time period.

    .DESCRIPTION
    Retrieve counts of authentication attempts for a given time period

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER StartDate
    Start date in powershell notation $(Get-Date).AddDays(-30)

    .PARAMETER EndDate
    End date in powershell notation $(Get-Date).AddDays(-1)

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAuthenticationAttemptsReport -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [datetime]$StartDate,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [datetime]$EndDate
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/info/authentication_attempts'
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        if($PSBoundParameters.ContainsKey("StartDate"))
        {
            $parameter["mintime"] = $(ConvertTo-Epoch -Date $StartDate -Milliseconds)
        }
        if($PSBoundParameters.ContainsKey("EndDate"))
        {
            $parameter["maxtime"] = $(ConvertTo-Epoch -Date $EndDate -Milliseconds)
        }

        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoAuthenticationAttemptsReport.ps1' 77
#Region './Public/Get-DuoAuthenticationLog.ps1' -1

function Get-DuoAuthenticationLog {
    <#
    .SYNOPSIS
    Returns a paged list of authentication log events ranging from the last 180 days up to as recently as two minutes before the API request.

    .DESCRIPTION
    Returns a paged list of authentication log events ranging from the last 180 days up to as recently as two minutes before the API request.

    .PARAMETER ApiHostname
    Target API hostname
        E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER StartDate
    Start date in powershell notation $(Get-Date).AddDays(-30)

    .PARAMETER EndDate
    End date in powershell notation $(Get-Date).AddDays(-1)

    .PARAMETER IntegrationKeys
    An integration's integration_key or the key value for an application returned in the authentication log output.
    Default: Return logs for all applications.

    .PARAMETER UserIds
    A user's user_id or the key value for a user returned in the authentication log output.
    Default: Return logs for all users.

    .PARAMETER EventType
    The type of authentication event. One of:
    authentication: Return events for authentication attempts.
    enrollment: Return events related to a user completing Duo's inline enrollment.

    .PARAMETER Factor
    The factor or method used for an authentication attempt. One of:
    duo_push: Return events where the authentication factor was "Duo Push".
    phone_call: Return events where the authentication factor was a phone call.
    u2f_token: Return events where the authentication factor was a U2F token.
    hardware_token: Return events where the authentication factor was a hardware token passcode.
    bypass_code: Return events where the authentication factor was a bypass code.
    sms_passcode: Return events where the authentication factor was an SMS passcode.
    duo_mobile_passcode: Return events where the authentication factor was a passcode generated by "Duo Mobile".
    yubikey_code: Return events where the authentication factor was a Yubikey OTP token passcode.
    passcode: Return events where the authentication factor was a passcode not identified as another known type.
    digipass_go_7_token: Return events where the authentication factor was a Digipass GO 7 token purchased from Duo.
    WebAuthn Security Key: Return events where the authentication factor was a FIDO2 security key.
    WebAuthn Chrome Touch ID: Return events where the authentication factor was Apple Touch ID with the Chrome browser.
    WebAuthn Credential: Return events where the authentication factor was a WebAuthn authenticator other than a security key or Touch ID.
    not_available: Return events where the authentication factor is not available.
    sms_refresh: Return events where the user requested a refresh batch of SMS passcodes.
    remembered_device: Return events where the authentication factor was the remembered device token from a previous authentication success.
    trusted_network: Return events where the effective authentication factor was an authorized network.
    trusted_mobile_authenticator: Return events where the effective authentication factor Duo Mobile Inline Auth on an Android or iOS device.
    verified_duo_push: Return events where the authentication factor was "Verified Duo Push".

    .PARAMETER GroupIds
    A group's group_id or the key value for a group returned in the authentication log output.
    Default: Return logs for all groups.

    .PARAMETER PhoneNumbers
    A phone's number as returned in the authentication log output. If the phone has been given a text name then both are returned in the format name (number).
    Default: Return logs for all phone numbers used.

    .PARAMETER Reason
    The reason associated with an authentication attempt. One of:
    user_marked_fraud: Return events where authentication was denied because the end user explicitly marked "fraudulent".
    deny_unenrolled_user: Return events where authentication was denied because of the following policy: "deny not enrolled users".
    error: Return events where authentication was denied because of an error.
    locked_out: Return events generated by users that are locked out.
    user_disabled: Return events where authentication was denied because the user was disabled.
    user_cancelled: Return events where authentication was denied because the end user cancelled the request.
    invalid_passcode: Return events where authentication was denied because the passcode was invalid.
    no_response: Return events where authentication was denied because there was no response from the user.
    no_keys_pressed: Return events where authentication was denied because no keys were pressed to accept the auth.
    call_timed_out: Return events where authentication was denied because the call was not answered or call authentication timed out for an indeterminate reason.
    location_restricted: Return events where authentication was denied because the end user's location was restricted.
    factor_restricted: Return events where authentication was denied because the authentication method used was not allowed.
    platform_restricted: Return events where authentication was denied because the access platform was not allowed.
    version_restricted: Return events where authentication was denied because the software version was not allowed.
    rooted_device: Return events where authentication was denied because the approval device was rooted.
    no_screen_lock: Return events where authentication was denied because the approval device does not have screen lock enabled.
    touch_id_disabled: Return events where authentication was denied because the approval device's biometrics (fingerprint, Face ID or Touch ID) is disabled.
    no_disk_encryption: Return events where authentication was denied because the approval device did not have disk encryption enabled.
    anonymous_ip: Return events where authentication was denied because the authentication request came from an anonymous IP address.
    out_of_date: Return events where authentication was denied because the software was out of date.
    denied_by_policy: Return events where authentication was denied because of a policy.
    software_restricted: Return events where authentication was denied because of software restriction.
    no_duo_certificate_present: Return events where authentication was denied because there was no Duo certificate present.
    user_provided_invalid_certificate: Return events where authentication was denied because an invalid management certificate was provided.
    could_not_determine_if_endpoint_was_trusted: Return events where authentication was denied because it could not be determined if the endpoint was trusted.
    invalid_management_certificate_collection_state: Return events where authentication was denied because of an invalid management certificate collection state.
    no_referring_hostname_provided: Return events where authentication was denied because no referring hostname was provided.
    invalid_referring_hostname_provided: Return events where authentication was denied because an invalid referring hostname was provided.
    no_web_referer_match: Return events where authentication was denied because an invalid referring hostname did not match an application's hostnames list.
    endpoint_failed_google_verification: Return events where authentication was denied because the endpoint failed Google verification.
    endpoint_is_not_trusted: Return events where authentication was denied because the endpoint was not trusted.
    invalid_device: Return events where authentication was denied because the device was invalid.
    anomalous_push: Return events where authentication was denied because of an anomalous push.
    endpoint_is_not_in_management_system: Return events where authentication was denied because the endpoint is not in a management system.
    no_activated_duo_mobile_account: Return events where authentication was denied because the end user does not have an activated Duo Mobile app account.
    allow_unenrolled_user: Return events where authentication was successful because of the following policy: "allow not enrolled users".
    bypass_user: Return events where authentication was successful because a bypass code was used.
    trusted_network: Return events where authentication was successful because the end user was on a trusted network.
    remembered_device: Return events where authentication was successful because the end user was on a remembered device.
    trusted_location: Return events where authentication was successful because the end user was in a trusted location.
    user_approved: Return events where authentication was successful because the end user approved the authentication request.
    valid_passcode: Return events where authentication was successful because the end user used a valid passcode.
    allowed_by_policy: Return events where authentication was successful because of a policy.
    allow_unenrolled_user_on_trusted_network: Return events where authentication was successful because the unenrolled user's access device was on an authorized network.
    user_not_in_permitted_group: Return events where authentication was denied because the user did not belong to one of the Permitted Groups specified in the application's settings.
    verification_code_correct: Return events where authentication was successful because of a Verified Duo Push.
    verification_code_missing: Return events where authentication was denied because the user used an old version of Duo Mobile that does not support Verified Duo Push.
    verification_code_incorrect: Return events where authentication was denied because the user entered the wrong code when approving a Verified Duo Push.

    .PARAMETER Result
    The result of an authentication attempt. One of:
    success: Return "successful" authentication events.
    denied: Return "denied" authentication events.
    fraud: Return "fraudulent" authentication events.

    .PARAMETER Tokens
    A WebAuthn security key's webauthnkey or U2F security key's registration_id as returned in the authentication log output.
    Default: Return logs for security keys used.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoAuthenticationLog -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -StartDate $(Get-Date).AddDays(-30) -EndDate $(Get-Date).AddDays(-1)
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [datetime]$StartDate,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [datetime]$EndDate,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$IntegrationKeys,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$UserIds,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("authentication","enrollment")]
        [string]$EventType,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("duo_push","phone_call","u2f_token","hardware_token","bypass_code","sms_passcode","duo_mobile_passcode","yubikey_code","passcode","digipass_go_7_token","WebAuthn Security Key","WebAuthn Chrome Touch ID","WebAuthn Credential","not_available","sms_refresh","remembered_device","trusted_network","trusted_mobile_authenticator","verified_duo_push")]
        [string]$Factor,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$GroupIds,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$PhoneNumbers,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("user_marked_fraud","deny_unenrolled_user","error","locked_out","user_disabled","user_cancelled","invalid_passcode","no_response","no_keys_pressed","call_timed_out","location_restricted","factor_restricted","platform_restricted","version_restricted","rooted_device","no_screen_lock","touch_id_disabled","no_disk_encryption","anonymous_ip","out_of_date","denied_by_policy","software_restricted","no_duo_certificate_present","user_provided_invalid_certificate","could_not_determine_if_endpoint_was_trusted","invalid_management_certificate_collection_state","no_referring_hostname_provided","invalid_referring_hostname_provided","no_web_referer_match","endpoint_failed_google_verification","endpoint_is_not_trusted","invalid_device","anomalous_push","endpoint_is_not_in_management_system","no_activated_duo_mobile_account","allow_unenrolled_user","bypass_user","trusted_network","remembered_device","trusted_location","user_approved","valid_passcode","allowed_by_policy","allow_unenrolled_user_on_trusted_network","user_not_in_permitted_group","verification_code_correct","verification_code_missing","verification_code_incorrect")]
        [string]$Reason,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("success","denied","fraud")]
        [string]$Result,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$Tokens
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{
            mintime = $(ConvertTo-Epoch -Date $StartDate -Milliseconds)
            maxtime = $(ConvertTo-Epoch -Date $EndDate -Milliseconds)
        }
    }
    Process{
        [string]$apiPath = "/admin/v2/logs/authentication"

        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        if($PSBoundParameters.ContainsKey("IntegrationKeys"))
        {
            $parameter["applications"] = $IntegrationKeys
        }
        if($PSBoundParameters.ContainsKey("UserIds"))
        {
            $parameter["users"] = $UserIds
        }
        if($PSBoundParameters.ContainsKey("EventType"))
        {
            $parameter["event_types"] = $EventType
        }
        if($PSBoundParameters.ContainsKey("Factor"))
        {
            $parameter["factors"] = $Factor
        }
        if($PSBoundParameters.ContainsKey("GroupIds"))
        {
            $parameter["groups"] = $GroupIds
        }
        if($PSBoundParameters.ContainsKey("PhoneNumbers"))
        {
            $parameter["phone_numbers"] = $PhoneNumbers
        }
        if($PSBoundParameters.ContainsKey("Reason"))
        {
            $parameter["reasons"] = $Reason
        }
        if($PSBoundParameters.ContainsKey("Result"))
        {
            $parameter["results"] = $Result
        }
        if($PSBoundParameters.ContainsKey("Tokens"))
        {
            $parameter["tokens"] = $Tokens
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoAuthenticationLog.ps1' 243
#Region './Public/Get-DuoBypassCode.ps1' -1

function Get-DuoBypassCode {
    <#
    .SYNOPSIS
    Returns a paged list of information about all bypass codes.

    .DESCRIPTION
    Returns a paged list of information about all bypass codes

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER BypassCodeId
    Target group. When specified returns information about the group

    .PARAMETER ShowUsers
    When specified, BypassCodeId is mandatory.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoBypassCode -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$BypassCodeId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/bypass_codes'
        if($PSBoundParameters.ContainsKey("BypassCodeId"))
        {
            [string]$apiPath = "/admin/v1/bypass_codes/$($BypassCodeId)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoBypassCode.ps1' 69
#Region './Public/Get-DuoEndpoint.ps1' -1

function Get-DuoEndpoint {
    <#
    .SYNOPSIS
    Returns a list of endpoints.

    .DESCRIPTION
    Returns a list of endpoints

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER EndpointId
    Target group. When specified returns information about the group

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoEndpoint -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$EndpointId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/endpoints'
        if($PSBoundParameters.ContainsKey("EndpointId"))
        {
            [string]$apiPath = "/admin/v1/endpoints/$($EndpointId)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoEndpoint.ps1' 66
#Region './Public/Get-DuoGroup.ps1' -1

function Get-DuoGroup {
    <#
    .SYNOPSIS
    Returns a list of groups.

    .DESCRIPTION
    Returns a list of groups

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER GroupId
    Target group. When specified returns information about the group

    .PARAMETER ShowUsers
    When specified, GroupId is mandatory.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoGroup -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$GroupId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$ShowUsers
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/groups'
        if($PSBoundParameters.ContainsKey("GroupId"))
        {
            [string]$apiPath = "/admin/v2/groups/$($GroupId)"
            if($PSBoundParameters.ContainsKey("ShowUsers"))
            {
                $apiPath = "$($apiPath)/users"
            }

        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoGroup.ps1' 77
#Region './Public/Get-DuoGroupByUser.ps1' -1

function Get-DuoGroupByUser {
    <#
    .SYNOPSIS
    Returns a paged list of groups associated with the user.

    .DESCRIPTION
    Returns a paged list of groups associated with the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring


    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoGroupByUser -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -UserId "FJDLA930490JFA0DF9A"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        [string]$apiPath = "/admin/v1/users/$($UserId)/groups"
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = "$($AccountId)"
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoGroupByUser.ps1' 64
#Region './Public/Get-DuoHardwareToken.ps1' -1

function Get-DuoHardwareToken {
    <#
    .SYNOPSIS
    Returns a list of OTP hardware tokens.

    .DESCRIPTION
    Returns a list of OTP hardware tokens

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER TokenId
    Target Token ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoHardwareToken -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoHardwareToken -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -TokenId "FJDLA930490JFA0DF9A"

    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$TokenId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
        [string]$apiPath = '/admin/v1/tokens'
    }
    Process{
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = "$($AccountId)"
        }
        if($PSBoundParameters.ContainsKey("TokenId"))
        {
            [string]$apiPath = "/admin/v1/tokens/$($TokenId)"
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoHardwareToken.ps1' 69
#Region './Public/Get-DuoHardwareTokenByUser.ps1' -1

function Get-DuoHardwareTokenByUser {
    <#
    .SYNOPSIS
    Returns a paged list of OTP hardware tokens associated with the user.

    .DESCRIPTION
    Returns a paged list of OTP hardware tokens associated with the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring


    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoHardwareTokenByUser -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -UserId "FJDLA930490JFA0DF9A"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        [string]$apiPath = "/admin/v1/users/$($UserId)/tokens"
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = "$($AccountId)"
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoHardwareTokenByUser.ps1' 64
#Region './Public/Get-DuoIntegration.ps1' -1

function Get-DuoIntegration {
    <#
    .SYNOPSIS
    Returns a list of integrations.

    .DESCRIPTION
    Returns a list of integrations

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER Key
    Target group. When specified returns information about the group

    .PARAMETER ShowUsers
    When specified, Key is mandatory.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoIntegration -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Key,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$ShowUsers
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/integrations'
        if($PSBoundParameters.ContainsKey("Key"))
        {
            [string]$apiPath = "/admin/v1/integrations/$($Key)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoIntegration.ps1' 72
#Region './Public/Get-DuoLogo.ps1' -1

function Get-DuoLogo {
    <#
    .SYNOPSIS
    Returns the custom logo displayed in the Duo authentication prompt and Duo Mobile.

    .DESCRIPTION
    Returns the custom logo displayed in the Duo authentication prompt and Duo Mobile

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoLogo -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/logo'
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoLogo.ps1' 56
#Region './Public/Get-DuoOfflineEnrollmentLog.ps1' -1

function Get-DuoOfflineEnrollmentLog {
    <#
    .SYNOPSIS
    Returns a list of administrator log events..

    .DESCRIPTION
    Returns a list of administrator log events.

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER StartDate
    Start date in powershell notation $(Get-Date).AddDays(-30)

.EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoOfflineEnrollmentLog -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoOfflineEnrollmentLog -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -StartDate $(Get-Date).AddDays(-30)
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [datetime]$StartDate
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/logs/offline_enrollment'
        if($PSBoundParameters.datetime("StartDate"))
        {
            mintime = $(ConvertTo-Epoch -Date $StartDate)
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoOfflineEnrollmentLog.ps1' 71
#Region './Public/Get-DuoPhone.ps1' -1

function Get-DuoPhone {
    <#
    .SYNOPSIS
    Returns a list of Phones.

    .DESCRIPTION
    Returns a list of Phones

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER PhoneId
    Target Phone. When specified returns information about the Phone

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoPhone -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$PhoneId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/phones'
        if($PSBoundParameters.ContainsKey("PhoneId"))
        {
            [string]$apiPath = "/admin/v1/phones/$($PhoneId)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoPhone.ps1' 66
#Region './Public/Get-DuoPhoneByUser.ps1' -1

function Get-DuoPhoneByUser {
    <#
    .SYNOPSIS
    Returns a paged list of phones associated with the user

    .DESCRIPTION
    Returns a paged list of phones associated with the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring


    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoPhoneByUser -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -UserId "FJDLA930490JFA0DF9A"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        [string]$apiPath = "/admin/v1/users/$($UserId)/phones"
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = "$($AccountId)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoPhoneByUser.ps1' 68
#Region './Public/Get-DuoPolicy.ps1' -1

function Get-DuoPolicy {
    <#
    .SYNOPSIS
    Retrieve a complete set of all policies.

    .DESCRIPTION
    Retrieve a complete set of all policies

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER Key
    Target Policy key

    .PARAMETER Global
    When used, the global policy is returned

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoPolicy -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Key,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$Global
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v2/policies'
        if($PSBoundParameters.ContainsKey("Key"))
        {
            [string]$apiPath = "/admin/v2/groups/$($Key)"

        }
        if($PSBoundParameters.ContainsKey("Global"))
        {
            $apiPath = "/admin/v2/policies/global"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoPolicy.ps1' 77
#Region './Public/Get-DuoSetting.ps1' -1

function Get-DuoSetting {
    <#
    .SYNOPSIS
    Returns global Duo settings.

    .DESCRIPTION
    Returns global Duo settings

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoSetting -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/settings'
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoSetting.ps1' 56
#Region './Public/Get-DuoTelephonyCreditsUsedReport.ps1' -1

function Get-DuoTelephonyCreditsUsedReport {
    <#
    .SYNOPSIS
    Retrieve the number of telephony credits used in a given time period.

    .DESCRIPTION
    Retrieve the number of telephony credits used in a given time period

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER StartDate
    Start date in powershell notation $(Get-Date).AddDays(-30)

    .PARAMETER EndDate
    End date in powershell notation $(Get-Date).AddDays(-1)

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoTelephonyCreditsUsedReport -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [datetime]$StartDate,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [datetime]$EndDate
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/info/telephony_credits_used'
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        if($PSBoundParameters.ContainsKey("StartDate"))
        {
            $parameter["mintime"] = $(ConvertTo-Epoch -Date $StartDate -Milliseconds)
        }
        if($PSBoundParameters.ContainsKey("EndDate"))
        {
            $parameter["maxtime"] = $(ConvertTo-Epoch -Date $EndDate -Milliseconds)
        }

        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoTelephonyCreditsUsedReport.ps1' 77
#Region './Public/Get-DuoTrustMonitorEvent.ps1' -1

function Get-DuoTrustMonitorEvent {
    <#
    .SYNOPSIS
    Returns a list of events surfaced by Trust Monitor from the last 180 days.

    .DESCRIPTION
    Returns a list of events surfaced by Trust Monitor from the last 180 days.

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER StartDate
    Start date in powershell notation $(Get-Date).AddDays(-30)

    .PARAMETER EndDate
    End date in powershell notation $(Get-Date).AddDays(-1)

    .PARAMETER Type
    The type of security event:
    auth Return security events that are denied anomalous authentications.
    bypass_status_enabled Return security events that are bypass status enabled.
    device_registration Return security events that are device registrations.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoTrustMonitorEvent -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -StartDate $(Get-Date).AddDays(-30) -EndDate $(Get-Date).AddDays(-1)
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [datetime]$StartDate,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [datetime]$EndDate,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("auth","bypass_status_enabled","device_registration")]
        [string]$Type
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{
            mintime = $(ConvertTo-Epoch -Date $StartDate)
            maxtime = $(ConvertTo-Epoch -Date $EndDate)

        }
    }
    Process{
        [string]$apiPath = '/admin/v1/logs/offline_enrollment'
        if($PSBoundParameters.datetime("Type"))
        {
            type = "$($Type)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoTrustMonitorEvent.ps1' 86
#Region './Public/Get-DuoUser.ps1' -1

function Get-DuoUser {
    <#
    .SYNOPSIS
    Returns a list of users.

    .DESCRIPTION
    Returns a list of users

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER Username
    Specify a user name (or username alias) to look up a single user

    .PARAMETER Email
    Specify an email address to look up a single user.

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoUser -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoUser -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -Username 'john.doe'

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoUser -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -Email 'john.doe@example.com

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoUser -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -UserId "FJDLA930490JFA0DF9A"

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_ADMIN' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoUser -ApiHostname $ApiHostname -Credential $Credential
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Username,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Email,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
        [string]$apiPath = '/admin/v1/users'
    }
    Process{
        if($PSBoundParameters.ContainsKey("Username"))
        {
            $parameter["username"] = "$($Username)"
        }
        if($PSBoundParameters.ContainsKey("Email"))
        {
            $parameter["email"] = "$($Email)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = "$($AccountId)"
        }
        if($PSBoundParameters.ContainsKey("UserId"))
        {
            [string]$apiPath = "/admin/v1/users/$($UserId)"
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoUser.ps1' 106
#Region './Public/Get-DuoUserBypassCode.ps1' -1

function Get-DuoUserBypassCode {
    <#
    .SYNOPSIS
    Returns a paged list of bypass code metadata associated with the user.

    .DESCRIPTION
    Returns a paged list of bypass code metadata associated with the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring


    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoUserBypassCode -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -UserId "FJDLA930490JFA0DF9A"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        [string]$apiPath = "/admin/v1/users/$($UserId)/bypass_codes"
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = "$($AccountId)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoUserBypassCode.ps1' 68
#Region './Public/Get-DuoUsersWithAuthAttemptsReport.ps1' -1

function Get-DuoUsersWithAuthAttemptsReport {
    <#
    .SYNOPSIS
    Retrieve counts of users with authentication attempts for a given time period.

    .DESCRIPTION
    Retrieve counts of users with authentication attempts for a given time period

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER StartDate
    Start date in powershell notation $(Get-Date).AddDays(-30)

    .PARAMETER EndDate
    End date in powershell notation $(Get-Date).AddDays(-1)

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoUsersWithAuthAttemptsReport -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [datetime]$StartDate,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [datetime]$EndDate
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/info/authentication_attempts'
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        if($PSBoundParameters.ContainsKey("StartDate"))
        {
            $parameter["mintime"] = $(ConvertTo-Epoch -Date $StartDate -Milliseconds)
        }
        if($PSBoundParameters.ContainsKey("EndDate"))
        {
            $parameter["maxtime"] = $(ConvertTo-Epoch -Date $EndDate -Milliseconds)
        }

        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoUsersWithAuthAttemptsReport.ps1' 77
#Region './Public/Get-DuoWebAuthnCredential.ps1' -1

function Get-DuoWebAuthnCredential {
    <#
    .SYNOPSIS
    Returns a list of all registered WebAuthn credentials.

    .DESCRIPTION
    Returns a list of all registered WebAuthn credentials

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER Key
    Target Key

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoWebAuthnCredential -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Key
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        [string]$apiPath = '/admin/v1/webauthncredentials'
        if($PSBoundParameters.ContainsKey("Key"))
        {
            [string]$apiPath = "/admin/v1/webauthncredentials/$($Key)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoWebAuthnCredential.ps1' 66
#Region './Public/Get-DuoWebAuthnCredentialByUser.ps1' -1

function Get-DuoWebAuthnCredentialByUser {
    <#
    .SYNOPSIS
    Returns a list of WebAuthn credentials associated with the user .

    .DESCRIPTION
    Returns a list of WebAuthn credentials associated with the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring


    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoWebAuthnCredentialByUser -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS" -UserId "FJDLA930490JFA0DF9A"
    #>

    [cmdletbinding()]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        [string]$apiPath = "/admin/v1/users/$($UserId)/webauthncredentials"
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = "$($AccountId)"
        }
        if($PSBoundParameters.ContainsKey("AccountId"))
        {
            $parameter["account_id"] = $AccountId
        }
        do{
            $temp = Invoke-DuoApi -ApiPath $apiPath -Method GET -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
            $output += $temp.response
            $parameter["offset"] = "$($temp.metadata.next_offset)"
        }
        while($temp.metadata.next_offset)
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Get-DuoWebAuthnCredentialByUser.ps1' 68
#Region './Public/Limit-DuoAdministratorAuthFactor.ps1' -1

function Limit-DuoAdministratorAuthFactor {
    <#
    .SYNOPSIS
    Enable or disable secondary authentication methods permitted for administrator log on to the Duo Admin Panel

    .DESCRIPTION
    Enable or disable secondary authentication methods permitted for administrator log on to the Duo Admin Panel

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Limit-DuoAdministratorAuthFactor -AdministratorId "AS0DF9AS0FU0ASF" -Role "Read-only" -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$HardwareTokenEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$MobileOtpEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$PushEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$SmsEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$VoiceEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$WebauthnEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$YubikeyEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Update administrator"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)"
            if($PSBoundParameters.ContainsKey("HardwareTokenEnabled"))
            {
                $parameter["hardware_token_enabled"] = "$($HardwareTokenEnabled)"
            }
            if($PSBoundParameters.ContainsKey("MobileOtpEnabled"))
            {
                $parameter["mobile_otp_enabled"] = "$($MobileOtpEnabled)"
            }
            if($PSBoundParameters.ContainsKey("PushEnabled"))
            {
                $parameter["push_enabled"] = "$($PushEnabled)"
            }
            if($PSBoundParameters.ContainsKey("SmsEnabled"))
            {
                $parameter["sms_enabled"] = "$($SmsEnabled)"
            }
            if($PSBoundParameters.ContainsKey("VoiceEnabled"))
            {
                $parameter["voice_enabled"] = "$($VoiceEnabled)"
            }
            if($PSBoundParameters.ContainsKey("WebauthnEnabled"))
            {
                $parameter["webauthn_enabled"] = "$($WebauthnEnabled)"
            }
            if($PSBoundParameters.ContainsKey("YubikeyEnabled"))
            {
                $parameter["yubikey_enabled"] = "$($YubikeyEnabled)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Limit-DuoAdministratorAuthFactor.ps1' 109
#Region './Public/New-DuoAccount.ps1' -1

function New-DuoAccount {
    <#
    .SYNOPSIS
    Create a Child account

    .DESCRIPTION
    Create a Child account

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER Name
    The name of the group to create

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoAccount -ApiHostname $ApiHostname -Credential $Credential -Name "MyNewAccount"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Name
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Create Child account"))
        {
            [string]$apiPath = '/admin/v1/groups'
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = "$($Name)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoAccount.ps1' 60
#Region './Public/New-DuoAdministrativeUnit.ps1' -1

function New-DuoAdministrativeUnit {
    <#
    .SYNOPSIS
    Create a new administrative unit

    .DESCRIPTION
    Create a new administrative unit

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER Name
    The name of the new administrative unit. Must be unique amongst all administrative units.

    .PARAMETER Description
    A description of the new administrative unit.

    .PARAMETER RestrictByGroups
    Does the new administrative unit specify groups? Default: false

    .PARAMETER RestrictByIntegrations
    Does the new administrative unit specify integrations? Default: false.

    .PARAMETER AdministratorIds
    One or more admin_id values to assign administrators to the new administrative unit.
    The administrator user must have restricted_by_admin_units set to true before attempting to assign them to an administrative unit via the API.

    .PARAMETER GroupIds
    One or more group_id values to assign groups to the new administrative unit.

    .PARAMETER IntegrationKeys
    One or more integration_key values to assign integrations to the new administrative unit.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoAdministrativeUnit -Name "MyUnit" -Description "New unit" -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Description,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RestrictByGroups,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RestrictByIntegrations,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$AdministratorIds,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$GroupIds,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$IntegrationKeys

    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{
            name = $Name
            description = $Description
            restrict_by_groups = $RestrictByGroups
        }

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Create new admin unit"))
        {
            [string]$apiPath = '/admin/v1/administrative_unit'

            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            if($PSBoundParameters.ContainsKey("RestrictByIntegrations"))
            {
                $parameter["restrict_by_integrations"] = $($RestrictByIntegrations)
            }
            if($PSBoundParameters.ContainsKey("AdministratorIds"))
            {
                $parameter["admins"] = $($AdministratorIds)
            }
            if($PSBoundParameters.ContainsKey("GroupIds"))
            {
                $parameter["groups"] = $($GroupIds)
            }
            if($PSBoundParameters.ContainsKey("IntegrationKeys"))
            {
                $parameter["integrations"] = $($IntegrationKeys)
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoAdministrativeUnit.ps1' 125
#Region './Public/New-DuoAdministrator.ps1' -1

function New-DuoAdministrator {
    <#
    .SYNOPSIS
    Create a new administrator

    .DESCRIPTION
    Create a new administrator

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER Name
    Name for the new administrator.

    .PARAMETER EmailAddress
    Valid email address for the new administrator.

    .PARAMETER PhoneNumber
    Phone number for the new administrator; E.164 format recommended (i.e. "+17345551212"). If no leading plus sign is provided then it is assumed to be a United States number and an implicit "+1" country code is prepended
    If this parameter is specified it cannot be empty.

    .PARAMETER Role
    The administrator's role.
    One of: "Owner", "Administrator", "Application Manager", "User Manager", "Help Desk", "Billing", "Phishing Manager", or "Read-only".
    The role names are case-sensitive. Defaults to "Owner" if not specified.

    .PARAMETER RestrictedByAdminUnits
    s this administrator restricted by an administrative unit assignment? Either true or false. Defaults to false if not specified.
    Must be set to true in order to add the admin to an administrative unit using the API.
    Note that attempting to set to true for admins with the "Owner" role results in a failure response.

    .PARAMETER SendEmail
    If set to $true, the activation link and an introductory message will be emailed to the new administrator. If set to $false, no email is sent, and the link is returned to the API method's caller only. Default: $false.

    .PARAMETER TokenId
    The token_id of the hardware token to associate with the administrator.

    .PARAMETER ValidDays
    Number of days before the activation link expires. Default: 7 Maximum:: 31

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoAdministrator -Name "Bob" -EmailAddress "bob@example.com" -Role "Read-only" -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$EmailAddress,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateScript({
            if($PSItem -inotmatch '^(\+|\d)(\d+){8,12}$')
            {
                throw "Phone Number must be in E.164 Format. i.e. '+17345551212'. If no leading plus sign is provided then it is assumed to be a United States number and an implicit '+1' country code is prepended"
            }
            return $true
        })]
        [string]$PhoneNumber,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("Owner", "Administrator", "Application Manager", "User Manager", "Help Desk", "Billing", "Phishing Manager", "Read-only")]
        [string]$Role,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RestrictedByAdminUnits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$SendEmail,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$TokenId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(7,30)]
        [int]$ValidDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Create new admin"))
        {
            [string]$apiPath = '/admin/v1/admins'
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("EmailAddress"))
            {
                $parameter["email"] = "$($EmailAddress)"
            }
            if($PSBoundParameters.ContainsKey("PhoneNumber"))
            {
                $parameter["phone"] = "$($PhoneNumber)"
            }
            if($PSBoundParameters.ContainsKey("Role"))
            {
                $parameter["role"] = "$($Role)"
            }
            if($PSBoundParameters.ContainsKey("RestrictedByAdminUnits"))
            {
                $parameter["restricted_by_admin_units"] = $($RestrictedByAdminUnits)
            }
            if($PSBoundParameters.ContainsKey("SendEmail"))
            {
                $parameter["send_email"] = 1
            }
            if($PSBoundParameters.ContainsKey("TokenId"))
            {
                $parameter["token_id"] = "$($TokenId)"
            }
            if($PSBoundParameters.ContainsKey("ValidDays"))
            {
                $parameter["valid_days"] = $ValidDays
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoAdministrator.ps1' 154
#Region './Public/New-DuoAdministratorActivationLink.ps1' -1

function New-DuoAdministratorActivationLink {
    <#
    .SYNOPSIS
    Create a new administrator

    .DESCRIPTION
    Create a new administrator

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER Name
    Name for the new administrator.

    .PARAMETER EmailAddress
    Valid email address for the new administrator.

    .PARAMETER Role
    The administrator's role.
    One of: "Owner", "Administrator", "Application Manager", "User Manager", "Help Desk", "Billing", "Phishing Manager", or "Read-only".
    The role names are case-sensitive. Defaults to "Owner" if not specified.


    .PARAMETER SendEmail
    If set to $true, the activation link and an introductory message will be emailed to the new administrator. If set to $false, no email is sent, and the link is returned to the API method's caller only. Default: $false.

    .PARAMETER ValidDays
    Number of days before the activation link expires. Default: 7 Maximum:: 31

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoAdministratorActivationLink -Name "Bob" -EmailAddress "bob@example.com" -Role "Read-only" -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$EmailAddress,


        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("Owner", "Administrator", "Application Manager", "User Manager", "Help Desk", "Billing", "Phishing Manager", "Read-only")]
        [string]$Role,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$SendEmail,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(7,30)]
        [int]$ValidDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($EmailAddress, "Create new admin activation link"))
        {
            [string]$apiPath = '/admin/v1/admins/activations'
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("EmailAddress"))
            {
                $parameter["email"] = "$($EmailAddress)"
            }
            if($PSBoundParameters.ContainsKey("Role"))
            {
                $parameter["role"] = "$($Role)"
            }
            if($PSBoundParameters.ContainsKey("SendEmail"))
            {
                $parameter["send_email"] = 1
            }
            if($PSBoundParameters.ContainsKey("ValidDays"))
            {
                $parameter["valid_days"] = $ValidDays
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoAdministratorActivationLink.ps1' 115
#Region './Public/New-DuoAdministratorPendingActivationLink.ps1' -1

function New-DuoAdministratorPendingActivationLink {
    <#
    .SYNOPSIS
    Creates an activation link for the administrator pending activation

    .DESCRIPTION
    Creates an activation link for the administrator pending activation

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER AdministratorId
    Target Administrator ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoAdministratorActivationLink -ApiHostname $ApiHostname -AdministratorId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($AdministratorId, "Creates an activation link for the administrator"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)/activation_link"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoAdministratorPendingActivationLink.ps1' 65
#Region './Public/New-DuoBypassCode.ps1' -1

function New-DuoBypassCode {
    <#
    .SYNOPSIS
    Clear all existing bypass codes for the user and return a list of count newly generated bypass codes

    .DESCRIPTION
    Clear all existing bypass codes for the user and return a list of count newly generated bypass codes

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER UserId
    Target User ID

    .PARAMETER Count
    Number of new bypass codes to create. At most 10 codes (the default) can be created at a time. Codes will be generated randomly.

    .PARAMETER PreserveExisting
    Preserves existing bypass codes while creating new ones.
    If true and the request would result the target user reaching the limit of 100 codes per user,
    or if codes is used and specifies a bypass code that already exists for the target user,
    then an error is returned and no bypass codes are created for nor cleared from the user.

    .PARAMETER ReuseCount
    The number of times generated bypass codes can be used. If 0, the codes will have an infinite reuse_count. Default: 1.

    .PARAMETER ValidSeconds
    The number of seconds for which generated bypass codes remain valid. If 0 (the default) the codes will never expire.

    .PARAMETER AccountId
    Parameter description

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Admin' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoBypassCode -ApiHostname $ApiHostname -UserId 'JA0DSFA0SD8F0SDF' -Count 3 -PreserveExisting:$false -ValidSeconds 3600

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoBypassCode -ApiHostname $ApiHostname -UserId 'JA0DSFA0SD8F0SDF' -Count 3 -PreserveExisting:$false -ValidSeconds 3600 -AccountId 'SLDJAF89AS0DF'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(1,10)]
        [int]$Count,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$PreserveExisting,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(0,10)]
        [int]$ReuseCount,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$ValidSeconds,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Create bypass codes"))
        {
            [string]$apiPath = "/admin/v1/users/$($UserId)/bypass_codes"
            if($PSBoundParameters.ContainsKey("Count"))
            {
                $parameter["count"] = $($Count)
            }
            if($PSBoundParameters.ContainsKey("PreverveExisting"))
            {
                $parameter["preserve_existing"] = $($PreverveExisting)
            }
            if($PSBoundParameters.ContainsKey("ReuseCount"))
            {
                $parameter["reuse_count"] = $($ReuseCount)
            }
            if($PSBoundParameters.ContainsKey("ValidSeconds"))
            {
                $parameter["valid_seconds"] = $($ValidSeconds)
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoBypassCode.ps1' 116
#Region './Public/New-DuoGroup.ps1' -1

function New-DuoGroup {
    <#
    .SYNOPSIS
    Create a new group

    .DESCRIPTION
    Create a new group

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER Name
    The name of the group to create

    .PARAMETER Status
    The user's status. Allowed Values "active","bypass","disabled"
    "active" The user must complete secondary authentication. This is the default value if no status is specified.
    "bypass" The user will bypass secondary authentication after completing primary authentication.
    "disabled" The user will not be able to complete secondary authentication.

    .PARAMETER Description
    An optional description

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoGroup -ApiHostname $ApiHostname -Name 'MyGroup' -Status 'active' -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("active", "bypass","disabled")]
        [string]$Status,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Description,


        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Create new group"))
        {
            [string]$apiPath = '/admin/v1/groups'
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("Status"))
            {
                $parameter["status"] = "$($Status)"
            }
            if($PSBoundParameters.ContainsKey("Description"))
            {
                $parameter["desc"] = "$($Description)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoGroup.ps1' 95
#Region './Public/New-DuoHardwareToken.ps1' -1

function New-DuoHardwareToken {
    <#
    .SYNOPSIS
    Create a new hardware token

    .DESCRIPTION
    Create a new hardware token

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER Type
    The type of hardware token to import.

    .PARAMETER Serial
    The serial number of the token (maximum length 128 characters).

    .PARAMETER Secret
    The HOTP secret. This parameter is required for HOTP-6 and HOTP-8 hardware tokens.

    .PARAMETER coutner
    Initial value for the HOTP counter. This parameter is only valid for HOTP-6 and HOTP-8 hardware tokens. Default: 0.

    .PARAMETER PrivateSid
    The 12-character YubiKey private ID. This parameter is required for YubiKey hardware tokens.

    .PARAMETER AesKey
    The 32-character YubiKey AES key. This parameter is required for YubiKey hardware tokens.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoHardwareToken -Type h8 -Serial 'slkdfJLKSdLfjsdkjfLsjQ'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("h6","h8","yk")]
        [string]$Type,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateLength(0,128)]
        [string]$Serial,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Secret,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$counter,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$PrivateSid,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AesKey
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Create new Hardware Token"))
        {
            [string]$apiPath = '/admin/v1/tokens'
            if($PSBoundParameters.ContainsKey("Type"))
            {
                $parameter["type"] = "$($Type)"
            }
            if($PSBoundParameters.ContainsKey("Serial"))
            {
                $parameter["serial"] = "$($Serial)"
            }
            if($PSBoundParameters.ContainsKey("Secret"))
            {
                $parameter["secret"] = "$($Secret)"
            }
            if($PSBoundParameters.ContainsKey("Counter"))
            {
                $parameter["counter"] = "$($Counter)"
            }
            if($PSBoundParameters.ContainsKey("PrivateSid"))
            {
                $parameter["private_sid"] = "$($PrivateSid)"
            }
            if($PSBoundParameters.ContainsKey("AesKey"))
            {
                $parameter["aes_key"] = "$($AesKey)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoHardwareToken.ps1' 122
#Region './Public/New-DuoIntegration.ps1' -1

function New-DuoIntegration {
    <#
    .SYNOPSIS
    Create a new integration. The new integration key and secret key are randomly generated and returned in the response

    .DESCRIPTION
    Create a new integration. The new integration key and secret key are randomly generated and returned in the response

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER Name
    The name of the integration to create

    .PARAMETER Type
    The type of integration to create
    Allowed values: "1password","accountsapi","adfs","adminapi","aeries","agadobe_documentcloud","agaha","agasana","agaws","agatlassian-cloud","agbamboohr","agbarracuda-waf","agbluejeans","agbomgar","agbonusly","agbox","agbugsnag","agcanvas","agciscoasa","agclarizen","agcloudlock","agconfluence","agcrashplan","agcyberark","agdatadog","agdesk","agdigicert","agdng","agdocusign","agdropbox","agduo-adminpanel","agegnyte","agevernote","agexpensify","agfacebook","agfreshdesk","aggeneric","aggithub-business","aggithub-enterprise","aggoogle","aggotomeeting","aggreenhouse","aghackerone","aghackerrank","agheroku","aghipchat","agigloo","agintacct","agjamf-jss","agjira","agjitbit","aglooker","agmarketo","agmeraki","agmonday","agnamely","agnetdocuments","agnewrelic","agoffice365","agopendns","agpagerduty","agpaloalto-aperture","agpaloalto","agremedyforce","agringcentral","agrobin","agsalesforce","agsamanage","agsaucelabs","agsharefile","agsignalsciences","agslack","agsmartsheet","agstatuspageio","agsugarcrm","agsumologic","agsyncplicity","agtableau-online","agtableau","agudemy","aguservoice","agwebex","agwebex-controlhub","agworkday","agzendesk","agzoom","akamai-eaa","array","aws-directory-service","azure-ca","authapi","barracuda","bitium","bitwarden","bomgar","caradigm","cas","checkpoint","cisco","ciscofirepower","ciscoiseradius","ciscoradius","citrixcag","citrixns","clearpass","confluence","cyberark","cyberarkweb","dag","device","device-management-portal","dng","dng-rdp","dng-smb","dng-ssh","drawbridgenetworks","drupal","epic","f5bigip","f5bigipweb","f5firepass","fortinet","greyheller","huntress","jira","juniper","juniperuac","keeper","labtech","lastpass","ldapproxy","macos","merakiradius","myworkdrive","netmotion","oam","okta","onelogin","openvpn","openvpnas","owa","paloalto","partner_authapi","partner_websdk","pingfederate","portal","radius","rdgateway","rdp","rdweb","resilient","rest","rras","sailpoint","sailpointweb","samlidp","shibboleth","securex-dashboard","sonicwallsra","sophosutm","splunk","thycotic","tmg","uag","unix","verify","vmwareview","websdk","workday","wordpress"

    .PARAMETER AllowAllAdminMethods
    Grant an Admin API integration permission for all Admins methods

    .PARAMETER AllowAccountInfo
    If creating an Admin API integration, set this to grant it permission for all Account Info methods

    .PARAMETER AllowAllAdminIntegrations
    Grant an Admin API integration permission for all Integrations methods

    .PARAMETER AllowAllAdminLogs
    Grant an Admin API integration permission for all Logs methods

    .PARAMETER AllowAllAdminResources
    Grant an Admin API integration permission to retrieve objects like users, phones, and hardware tokens

    .PARAMETER AllowAllAdminSettings
    Grant an Admin API integration permission for all Settings methods

    .PARAMETER AllowAllAdminWriteResources
    Grant an Admin API integration permission to create and modify objects like users, phones, and hardware tokens.

    .PARAMETER PhoneCallGreeting
    Voice greeting read before the authentication instructions to users who authenticate with a phone callback

    .PARAMETER AllowedGrops
    An array of group IDs that are allowed to authenticate with the integration. If empty, all interations are allowed.
    Object limits: 100 interations per integration.

    .PARAMETER AllowNetworks
    An array of IP addresses, IP ranges, or CIDRs specifying the networks allowed to access this API integration. Only applicable to Accounts API and Admin API integrations.
    A given API integration may apply a network restriction to itself via API; use a different API integration to apply the network restriction, or edit the API application in the Duo Admin Panel GUI.

    .PARAMETER Notes
    Description of the integration

    .PARAMETER AllowSelfService
    Grant an integration permission to allow users to manage their own devices. This is only supported by integrations which allow for self service configuration

    .PARAMETER UsernameNormalization
    Policy for whether or not usernames should be altered before trying to match them to a user account.

    .PARAMETER AccountId
    Target Account Id

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoIntegration -Name "My Domain rdp" -Type "rdp" -ApiHostname $ApiHostname -Credential $Credential -AllowSelfService

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoIntegration -Name "My Domain owa" -Type "owa" -ApiHostname $ApiHostname -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("1password","accountsapi","adfs","adminapi","aeries","agadobe_documentcloud","agaha","agasana","agaws","agatlassian-cloud","agbamboohr","agbarracuda-waf","agbluejeans","agbomgar","agbonusly","agbox","agbugsnag","agcanvas","agciscoasa","agclarizen","agcloudlock","agconfluence","agcrashplan","agcyberark","agdatadog","agdesk","agdigicert","agdng","agdocusign","agdropbox","agduo-adminpanel","agegnyte","agevernote","agexpensify","agfacebook","agfreshdesk","aggeneric","aggithub-business","aggithub-enterprise","aggoogle","aggotomeeting","aggreenhouse","aghackerone","aghackerrank","agheroku","aghipchat","agigloo","agintacct","agjamf-jss","agjira","agjitbit","aglooker","agmarketo","agmeraki","agmonday","agnamely","agnetdocuments","agnewrelic","agoffice365","agopendns","agpagerduty","agpaloalto-aperture","agpaloalto","agremedyforce","agringcentral","agrobin","agsalesforce","agsamanage","agsaucelabs","agsharefile","agsignalsciences","agslack","agsmartsheet","agstatuspageio","agsugarcrm","agsumologic","agsyncplicity","agtableau-online","agtableau","agudemy","aguservoice","agwebex","agwebex-controlhub","agworkday","agzendesk","agzoom","akamai-eaa","array","aws-directory-service","azure-ca","authapi","barracuda","bitium","bitwarden","bomgar","caradigm","cas","checkpoint","cisco","ciscofirepower","ciscoiseradius","ciscoradius","citrixcag","citrixns","clearpass","confluence","cyberark","cyberarkweb","dag","device","device-management-portal","dng","dng-rdp","dng-smb","dng-ssh","drawbridgenetworks","drupal","epic","f5bigip","f5bigipweb","f5firepass","fortinet","greyheller","huntress","jira","juniper","juniperuac","keeper","labtech","lastpass","ldapproxy","macos","merakiradius","myworkdrive","netmotion","oam","okta","onelogin","openvpn","openvpnas","owa","paloalto","partner_authapi","partner_websdk","pingfederate","portal","radius","rdgateway","rdp","rdweb","resilient","rest","rras","sailpoint","sailpointweb","samlidp","shibboleth","securex-dashboard","sonicwallsra","sophosutm","splunk","thycotic","tmg","uag","unix","verify","vmwareview","websdk","workday","wordpress")]
        [string]$Type,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminMethods,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAccountInfo,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminIntegrations,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminLogs,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminResources,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminSettings,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminWriteResources,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$PhoneCallGreeting,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateCount(0,100)]
        [array]$AllowedGrops,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$AllowNetworks,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Notes,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowSelfService,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("None","Simple")]
        [string]$UsernameNormalization,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Create new Integration"))
        {
            [string]$apiPath = '/admin/v1/integrations'
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("Type"))
            {
                $parameter["type"] = "$($Type)"
            }
            if($PSBoundParameters.ContainsKey("AllowAllAdminMethods"))
            {
                $parameter["adminapi_admins"] = 1
            }
            if($PSBoundParameters.ContainsKey("AllowAccountInfo"))
            {
                $parameter["adminapi_info"] = 1
            }
            if($PSBoundParameters.ContainsKey("AllowAllAdminIntegrations"))
            {
                $parameter["adminapi_integrations"] = 1
            }
            if($PSBoundParameters.ContainsKey("AllowAllAdminLogs"))
            {
                $parameter["adminapi_read_log"] = 1
            }
            if($PSBoundParameters.ContainsKey("AllowAllAdminResources"))
            {
                $parameter["adminapi_read_resource"] = 1
            }
            if($PSBoundParameters.ContainsKey("AllowAllAdminWriteResources"))
            {
                $parameter["adminapi_write_resource"] = 1
            }
            if($PSBoundParameters.ContainsKey("PhoneCallGreeting"))
            {
                $parameter["greeting"] = "$($PhoneCallGreeting)"
            }
            if($PSBoundParameters.ContainsKey("AllowedGroups"))
            {
                $parameter["groups_allowed"] = @($AllowedGrops)
            }
            if($PSBoundParameters.ContainsKey("AllowNetworks"))
            {
                $parameter["networks_for_api_access"] = @($AllowNetworks)
            }
            if($PSBoundParameters.ContainsKey("Notes"))
            {
                $parameter["notes"] = "$($Notes)"
            }
            if($PSBoundParameters.ContainsKey("AllowSelfService"))
            {
                $parameter["self_service_allowed"] = 1
            }
            if($PSBoundParameters.ContainsKey("UsernameNormalization"))
            {
                $parameter["user_normalization_policy"] = "$($UsernameNormalization)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoIntegration.ps1' 217
#Region './Public/New-DuoPhone.ps1' -1

function New-DuoPhone {
    <#
    .SYNOPSIS
    Create a new Phone

    .DESCRIPTION
    Create a new Phone

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER PhoneNumber
    The new phone number; E.164 format recommended (i.e. "+17345551212").
    If no leading plus sign is provided then it is assumed to be a United States number and an implicit "+1" country code is prepended.

    .PARAMETER Name
    Free-form label for the phone.

    .PARAMETER Extension
    The extension.

    .PARAMETER Type
    The type of phone. One of: "unknown", "mobile", or "landline".

    .PARAMETER Platform
    The phone platform. One of: "unknown", "google android", "apple ios", "windows phone 7", "rim blackberry", "java j2me", "palm webos", "symbian os", "windows mobile", or "generic smartphone".

    "windows phone" is accepted as a synonym for "windows phone 7". This includes devices running Windows Phone 8.

    If a smartphone's exact platform is unknown but it will have Duo Mobile installed, use "generic smartphone" and generate an activation code. When the phone is activated its platform will be automatically detected.

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>New-DuoPhone -ApiHostname $ApiHostname -Name 'MyPhone' -PhoneNumber '+18888888888' -Type "mobile" -Platform "generic smartphone" -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateScript({
            if($PSItem -inotmatch '^(\+|\d)(\d+){8,12}$')
            {
                throw "Phone Number must be in E.164 Format. i.e. '+17345551212'. If no leading plus sign is provided then it is assumed to be a United States number and an implicit '+1' country code is prepended"
            }
            return $true
        })]
        [string]$PhoneNumber,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Extension,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("unknown", "mobile", "landline")]
        [string]$Type,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("unknown", "google android", "apple ios", "windows phone 7", "rim blackberry", "java j2me", "palm webos", "symbian os", "windows mobile", "generic smartphone")]
        [string]$Platform = "generic smartphone"

    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Create new Phone"))
        {
            [string]$apiPath = '/admin/v1/phones'
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            if($PSBoundParameters.ContainsKey("PhoneNumber"))
            {
                $parameter["number"] = "$($PhoneNumber)"
            }
            else {
                Write-Warning "No number was provided. A phone with a smartphone platform but no number is considered a tablet"
            }
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("Extension"))
            {
                $parameter["extension"] = "$($Extension)"
            }
            if($PSBoundParameters.ContainsKey("Type"))
            {
                $parameter["type"] = "$($Type)"
            }
            if($PSBoundParameters.ContainsKey("Platform"))
            {
                $parameter["platform"] = "$($Platform)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoPhone.ps1' 128
#Region './Public/New-DuoPhoneActivationCode.ps1' -1

function New-DuoPhoneActivationCode {
    <#
    .SYNOPSIS
    Generate a Duo Mobile activation code. This method will fail if the phone's type or platform are Unknown.

    .DESCRIPTION
    Generate a Duo Mobile activation code. This method will fail if the phone's type or platform are Unknown.

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER PhoneId
    Target Phone ID

    .PARAMETER ValidSeconds
    The number of seconds this activation code remains valid. Default: 86400 (one day). Expiration not supported for legacy phone platforms that support passcode generation only (not Duo Push).

    .PARAMETER ShowInstallUrl
    Specify to also return an installation URL for Duo Mobile

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Add-DuoPhoneActivationCode -ApiHostname $ApiHostname -ValidSeconds 3600 -ShowInstallUrl -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$PhoneId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$ValidSeconds,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$ShowInstallUrl,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Create new Activation Code"))
        {
            [string]$apiPath = "/admin/v1/phones/$($PhoneId)/activation_url"
            if($PSBoundParameters.ContainsKey("ValidSeconds"))
            {
                $parameter["valid_sec"] = $ValidSeconds
            }
            if($PSBoundParameters.ContainsKey("ShowInstallUrl"))
            {
                $parameter["install"] = 1
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoPhoneActivationCode.ps1' 86
#Region './Public/New-DuoPolicy.ps1' -1

function New-DuoPolicy {
    <#
    .SYNOPSIS
    Creates a new custom policy with specified parameters.

    .DESCRIPTION
    Creates a new custom policy with specified parameters.

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER Name
    The name of the policy to create. Policy names do not have to be unique.

    The name parameter may be used instead, but it will be deprecated in a future release.
    Please use policy_name for best results.

    .PARAMETER AffectAllApps
    Values are one of:
    inactive - (default) Use _list keys to specify how policy is applied.
    replace-policy - Apply this policy to all apps, replacing any existing policy.
    apply-policy - Apply this policy to all apps that don’t have a policy applied already.
    unassign-policy - Remove this policy from all apps to which it is applied.
    Warning: Setting this key to any value other than inactive will make changes to all your applications.

    .PARAMETER ApplyList
    An array of apps (specified with app_integration_key) to which to apply this policy.
    If an app in the list has another policy applied, that policy is kept.

    .PARAMETER ReplaceList
    The array of applications (specified with app_integration_key) to which to apply this policy.
    Warning: If the policy is already applied to applications not in the list, it will be removed from those applications.

    .PARAMETER UnassignList
    An array of apps (specified with integration_key) from which to remove this policy.
    If an app in the list has another policy applied, that policy is kept.

    .PARAMETER ApplyGroupPolicyList
    A set of groups (specified with group_id_list) to which to apply this policy.

    .PARAMETER GroupPolicyApplyOrder
    Values are one of:
    existing - (default) If the group policy being applied already exists for this application, keep its place in the stack. If it doesn’t exist, add it to the top of the stack.
    top - Place this policy on the top of the group policy stack.
    bottom - Place this policy on the bottom of the group policy stack.

    .PARAMETER ReplaceGroupPolicyList
    A set of groups (specified with group_id_list) to which to apply this policy.
    If you specify a blank array ([]) as a value, all groups applied to this policy in this app will be replaced with nothing (that is, unassigned).

    .PARAMETER UnassignGroupPolicyList
    A set of groups (specified with group_id_list) from which to remove this policy.

    .PARAMETER AnonymousAccessBehavior
    Defines what happens when a user on an anonymous network attempts to access resources. One of no-action (default), require-mfa, or deny.

    .PARAMETER AllowedAuthList
    Comma-separated list of allowed authentication methods. The list defaults to: duo-push, hardware-token, webauthn-platform, webauthn-roaming, and sms.
    If Duo Passwordless is turned on for your account, there are three additional authentication methods available: duo-push-pwl, webauthn-platform-pwl, and webauthn-roaming-pwl.

    .PARAMETER AutoRetrySms
    Is true if a new SMS passcode will be sent up to 3 times when delivery fails. Otherwise false (default).
    Any retries will use additional telephony credits

    .PARAMETER BlockedAuthList
    Comma-separated list of blocked authentication methods.
    The list defaults to: duo-passcode and phonecall

    .PARAMETER RequireVerifiedPush
    Is true (default) if the user logging in must verify the push by entering the number provided on their authentication device.
    Otherwise false. Applies if duo-push is in the allowed_auth_list.

    .PARAMETER VerifiedPushDigits
    The number of digits a verified push requires the user to enter. An integer between 3 and 6, inclusive. Defaults to 3

    .PARAMETER UserAuthBehavior
    Defines the behavior when a user authenticates. One of:
    enforce (default): Requires 2FA or enrollment when applicable, unless another policy supersedes it.
    bypass: Skips 2FA and enrollment, unless another policy supersedes it.
    deny: Denies authentication to all users.
    Affects all users when enabled.

    .PARAMETER NoMfaRequiredIpList
    Comma-separated list of public IP addresses for which 2FA is not required.
    IP address lists can contain individual IPs, IP ranges and IP ranges in CIDR notation.
    Example: ["192.0.2.8", "198.51.100.0-198.51.100.20", "203.0.113.0/24"]

    .PARAMETER RequireEnrollment
    Is true (default) if users logging in from these IP addresses must enroll in Duo.
    Otherwise false. At least one value must be in the ip_list to change this value.

    .PARAMETER MfaRequiredIpList
    Comma-separated list of public IP addresses for which MFA is required.
    IP address lists can contain individual IPs, IP ranges and IP ranges in CIDR notation.
    Example: ["192.0.2.8", "198.51.100.0-198.51.100.20", "203.0.113.0/24"]

    .PARAMETER DenyOtherAccess
    Is true if users must log in from IP addresses listed in one of the ip_list keys above.
    Otherwise false (default). At least one IP address must be in either of the ip_list keys above to change this value.
    This key is available in the Premier and Advantage editions.

    .PARAMETER AllowedBrowsersList
    Comma-separated list of allowed browsers. Default behavior permits all browsers.

    .PARAMETER BlockedBrowsersList
    Comma-separated list of blocked browsers. Default: none.

    .PARAMETER OutOfDateBehavior
    Value is one of warn-only, warn-and-block, or no-remediation (default).
    This affects all browsers in the allowed_browsers_list.

    .PARAMETER BrowserMaxOutOfDateDays
    The number of days that a browser may be out of date before access to it is blocked (out_of_date_behavior must be warn-and-block for the browser to be blocked).
    Value is one of 0, 14, 30 (default), 60, 90, 180, or 365.
    Other values are invalid.

    .PARAMETER RequiresDha
    Comma-separated list of operating systems that require the Duo Device Health App (one or more of macos or windows).
    Listing an operating system here is the equivalent of setting “Enforcing” for that OS when editing a policy in the Admin Panel

    .PARAMETER PromptToInstallDha
    Comma-separated list of operating systems that will prompt to install the Duo Device Health App during enrollment (one or more of macos or windows).

    .PARAMETER EnforceFirewall
    Comma-separated list of operating systems that will require a firewall to be active (one or more of macos or windows).
    This key is available in the Premier and Advantage editions.

    .PARAMETER EnforceEncryption
    Comma-separated list of operating systems that will require the hard drive to be encrypted (one or more of macos or windows).
    This key is available in the Premier and Advantage editions.

    .PARAMETER EnforceSystemPassword
    Comma-separated list of operating systems that will require a system password to be set (one or more of macos or windows).
    This key is available in the Premier and Advantage editions.

    .PARAMETER MacOsRemediationNote
    A text note (max 700 characters) with remediation instructions when an end user is blocked.
    This key is available in the Premier edition.

    .PARAMETER MacOsEndpointSecurityList
    Comma-separated list of Duo-supported endpoint security agents that are allowed.
    For agents in this list, the app will block access unless one of those agents is running.
    A complete list of macOS security agents is available in a drop-down when editing the policy in the Admin Panel.
    This key is available in the Premier edition.

    .PARAMETER WindowsEndpointSecurityList
    omma-separated list of Duo-supported endpoint security agents that are allowed.
    For agents in this list, the app will block access unless one of those agents is running.
    A complete list of Windows security agents is available in a drop-down when editing the policy in the Admin Panel.
    This key is available in the Premier edition.

    .PARAMETER WindowsRemediationNote
    A text note (max 700 characters) with remediation instructions when an end user is blocked.
    This key is available in the Premier edition.

    .PARAMETER RequireDuoAppUpdates
    Is true (default) if the Duo Mobile app must have up-to-date security patches. Otherwise false.

    .PARAMETER RequiresFullDiskEncryption
    Is true if the device used for authentication requires full-disk encryption. Otherwise false (default).

    .PARAMETER RequiresMobileDeviceBiometrics
    Is true if the mobile device used to authenticate requires Apple Touch ID, Face ID, or Android Fingerprint as additional verification when approving Duo Push login requests. Otherwise false (default).

    .PARAMETER NewUserBehavior
    Controls what happens after an unenrolled user passes primary authentication. One of:
    enroll (default): Require the user to enroll whenever possible.
    no-mfa: MFA is not required for unknown users; unenrolled users must enroll.
    deny: Denies authentication to unenrolled users.


    .PARAMETER AllowUnrestrictedOsList
    Comma-separated list of operating systems that are allowed with no constraints or warnings.
    AllowUnrestrictedOsList and BlockOsList must not contain the same values.

    .PARAMETER BlockOsList
    Comma-separated list of operating systems that are not allowed.
    AllowUnrestrictedOsList and BlockOsList must not contain the same values.
    Blocked Android or iOS versions will not be able to authenticate using Duo Push or Duo Mobile passcodes.

    .PARAMETER OperatingSystemToRestrict
    Operating systems that can be further restricted: android, ios, macos, and windows.

    .PARAMETER OsWarnPolicy
    Indicates when the user should be warned that their OS is out of date. Value is one of:
    no-remediation (default): No version checking; equivalent to “Never” when editing the policy in the UI.
    end-of-life: OS vendor no longer releases security updates.
    not-up-to-date: OS is not at the most recent patch release version.
    less-than-latest: OS is not at the most recently released version.
    less-than-version: OS is older than the version specified in warn_version.


    .PARAMETER OsWarnVersion
    The specific OS version (from the list in the edit policy UI) subject to the out-of-date warning.
    Applicable only if warn_policy is less-than-version.

    .PARAMETER OsWarnRemediationDays
    Number of days that the user will be warned.
    Value is one of 0, 14, 30 (default), 60, 90, 180, or 365.

    .PARAMETER OsBlockPolicy
    Indicates when the user will be blocked from access.
    Values are the same as warn_policy.

    .PARAMETER OsBlockVersion
    The specific OS version (from the list in the edit policy UI) that is being blocked.
    Values are the same as warn_version.
    Applicable only if block_policy is less-than-version.

    .PARAMETER OsBlockRemediationDays
    Number of days before the user will be blocked.
    Values are the same as warn_remediation_days.

    .PARAMETER FlashPlugin
    Specify how Flash plugins are treated. Value is one of allow-all or block-all (default).

    .PARAMETER JavaPlugin
    Specify how Java plugins are treated. Value is one of:
    allow-all: No restrictions.
    warn-only (default): Warn if plugin is out of date.
    warn-and-block: warn if out of date; block after java_max_ood_days.
    block-all: Blocked; no access.


    .PARAMETER JavaMaxOutOfDateDays
    The number of days that Java plugins may be out of date before access is blocked (java must be warn-and-block for the plugin to be blocked).
    Value is one of 0, 14, 30 (default), 60, 90, 180, or 365.
    Other values are invalid.

    .PARAMETER BrowserAppsEnabled
    Is true if devices are remembered for browser-based apps. Otherwise false (default).

    .PARAMETER BrowserAppsRememberMethod
    One of user-based (default) or risk-based. risk-based only available in the Premier and Advantage editions.

    .PARAMETER BrowserAppsUserBasedConfirmPerApp
    s true if the user must confirm for each browser-based app separately. Otherwise false (default).

    .PARAMETER BrowserAppsUserBasedMaxTimeUnits
    One of days or hours (default).

    .PARAMETER BrowserAppsUserBasedMaxTimeValue
    If max_time_units is set to:
    days: an integer 1 to 365, inclusive.
    hours: an integer 1 to 8760, inclusive.
    Defaults to 12.

    .PARAMETER BrowserAppsRiskBasedMaxTimeUnits
    One of days or hours (default).

    .PARAMETER BrowserAppsRiskBasedMaxTimeValue
    If max_time_units is set to:
    days: an integer 1 to 365, inclusive.
    hours: an integer 1 to 8760, inclusive.
    Defaults to 30.

    .PARAMETER WindowsLogonEnabled
    Is true if devices are remembered for Windows Logon. Otherwise false (default).
    2FA will be enforced after users sign out, reboot, or change networks.

    .PARAMETER WindowsLogonMaxTimeUnits
    One of days (default) or hours.

    .PARAMETER WindowsLogonMaxTimeValue
    If max_time_units is set to:
    days: an integer 1 to 365, inclusive.
    hours: an integer 1 to 8760, inclusive.
    Defaults to 30.

    .PARAMETER LimitToRiskBasedAuthMethods
    s true if the user is limited to risk-based authentication methods when Duo detects a higher-risk authentication. Otherwise false (default).

    .PARAMETER RiskBasedVerifiedPushDigits
    The number of digits a verified push requires the user logging in to enter. An integer between 3 and 6, inclusive. Defaults to 6.

    .PARAMETER RequiresScreenLock
    Is true (default) if the device must have a screen lock to be allowed for authentication. Otherwise false. Applies to iOS (8 and up) and Android.

    .PARAMETER BlockTamperedDevices
    Is true (default) if iOS or Android devices that are rooted or otherwise tampered with are not allowed for authentication. Otherwise false.

    .PARAMETER TrustedEndpointChecking
    Value is one of allow-all (default), require-trusted, or not-configured. Value will be not-configured if Trusted Endpoints management systems have not been configured.
    Trusted endpoints will still be checked for reporting purposes if allow-all is set, but untrusted endpoints will be allowed.

    .PARAMETER CiscoSecureEndpointCanBlock
    Is true if Cisco Secure Endpoint is allowed to block compromised endpoints. Otherwise false (default).

    .PARAMETER TrustedEndpointCheckingMobile
    Allowed values and default are the same as trusted_endpoint_checking.
    Duo recommends not setting this value separately from trusted_endpoint_checking.
    Since the user-agent string is self-reported by the browser, it's possible to manipulate it from the client side to change the value reported to Duo, with the potential effect of bypassing a policy intended to block access.

    .PARAMETER RequireMfaCountriesList
    List of one or more country codes. If the user’s location matches one of the codes, that user is required to use MFA to authenticate.

    .PARAMETER DenyAccessCountriesList
    List of one or more country codes. If the user’s location matches one of the codes, that user is denied access.

    .PARAMETER AllowAccessNoMfaCountriesList
    List of one or more country codes. If the user’s location matches one of the codes, that user is allowed access without 2FA.

    .PARAMETER IgnoreLocationCountriesList
    List of one or more country codes. If the user’s location matches one of the codes, no action is taken.

    .PARAMETER DefaultAction
    Indicates behavior for country codes that aren’t in any list. Values are one of:
    deny-access: User is denied access.
    ignore-location (default): No action is taken.
    require-mfa: User must use MFA to authenticate.
    allow-access-no-2fa: User is allowed access without 2FA.

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>New-DUOPolicy -Name "MyNewPolicy" -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High", DefaultParameterSetName="A")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("inactive","replace-policy","apply-policy","unassign-policy")]
        [string]$AffectAllApps,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$ApplyList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$ReplaceList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$UnassignList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$ApplyGroupPolicyList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("existing","top","bottom")]
        [string]$GroupPolicyApplyOrder,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$ReplaceGroupPolicyList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$UnassignGroupPolicyList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("no-action","require-mfa","deny")]
        [string]$AnonymousAccessBehavior,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$AllowedAuthList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AutoRetrySms,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$BlockedAuthList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequireVerifiedPush,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(3,6)]
        [int]$VerifiedPushDigits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("enforce","bypass","deny")]
        [string]$UserAuthBehavior,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$NoMfaRequiredIpList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequireEnrollment,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$MfaRequiredIpList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$DenyOtherAccess,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$AllowedBrowsersList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$BlockedBrowsersList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("warn-only","warn-and-block","no-remediation")]
        [string]$OutOfDateBehavior,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet(0,14,30,60,90,180,365)]
        [int]$BrowserMaxOutOfDateDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$RequiresDha,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$PromptToInstallDha,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$EnforceFirewall,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$EnforceEncryption,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$EnforceSystemPassword,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$MacOsEndpointSecurityList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateLength(0,700)]
        [string]$MacOsRemediationNote,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$WindowsEndpointSecurityList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateLength(0,700)]
        [string]$WindowsRemediationNote,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequireDuoAppUpdates,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequiresFullDiskEncryption,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequiresMobileDeviceBiometrics,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("enroll","no-mfa","deny")]
        [string]$NewUserBehavior,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateScript({
            foreach($value in $_)
            {
                if($value -inotin @("android","blackberry","chromeos","ios","linux","macos","windows","windowsphone","unknownos"))
                {
                    throw 'Invalid Entry ' + $value + '. Allowed Values: "android","blackberry","chromeos","ios","linux","macos","windows","windowsphone", and "unknownos"'
                }
            }
            return $true
        })]
        [array]$AllowUnrestrictedOsList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateScript({
            foreach($value in $_)
            {
                if($value -inotin @("android","blackberry","chromeos","ios","linux","macos","windows","windowsphone","unknownos"))
                {
                    throw 'Invalid Entry ' + $value + '. Allowed Values: "android","blackberry","chromeos","ios","linux","macos","windows","windowsphone", and "unknownos"'
                }
            }
            return $true
        })]
        [array]$BlockOsList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("android", "ios", "macos", "windows")]
        [string]$OperatingSystemToRestrict,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("no-remediation","end-of-life","not-up-to-date","less-than-latest","less-than-version")]
        [string]$OsWarnPolicy,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$OsWarnVersion,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet(0,14,30,60,90,180,365)]
        [string]$OsWarnRemediationDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("no-remediation","end-of-life","not-up-to-date","less-than-latest","less-than-version")]
        [string]$OsBlockPolicy,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$OsBlockVersion,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet(0,14,30,60,90,180,365)]
        [string]$OsBlockRemediationDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("allow-all","block-all")]
        [string]$FlashPlugin,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("allow-all","warn-only","warn-and-block","block-all")]
        [string]$JavaPlugin,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet(0,14,30,60,90,180,365)]
        [string]$JavaMaxOutOfDateDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$BrowserAppsEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("user-based","risk-based")]
        [string]$BrowserAppsRememberMethod,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$BrowserAppsUserBasedConfirmPerApp,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("days","hours")]
        [string]$BrowserAppsUserBasedMaxTimeUnits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$BrowserAppsUserBasedMaxTimeValue,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("days","hours")]
        [string]$BrowserAppsRiskBasedMaxTimeUnits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$BrowserAppsRiskBasedMaxTimeValue,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$WindowsLogonEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("days","hours")]
        [string]$WindowsLogonMaxTimeUnits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$WindowsLogonMaxTimeValue,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$LimitToRiskBasedAuthMethods,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(3,6)]
        [int]$RiskBasedVerifiedPushDigits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequiresScreenLock,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$BlockTamperedDevices,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("allow-all","require-trusted","not-configured")]
        [string]$TrustedEndpointChecking,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$CiscoSecureEndpointCanBlock,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("allow-all","require-trusted","not-configured")]
        [string]$TrustedEndpointCheckingMobile,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$RequireMfaCountriesList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$DenyAccessCountriesList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$AllowAccessNoMfaCountriesList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$IgnoreLocationCountriesList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("deny-access", "ignore-location","require-mfa","allow-access-no-2fa")]
        [string]$DefaultAction,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId

    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Create new policy"))
        {
            [string]$apiPath = "/admin/v2/policies"
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["policy_name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("AffectAllApps"))
            {
                $parameter["apply_to_apps"] = @{"affect_all_apps" = $($AffectAllApps)}
            }
            if($PSBoundParameters.ContainsKey("ApplyList"))
            {
                $parameter["apply_to_apps"] = @{"apply_list" = $($ApplyList)}
            }
            if($PSBoundParameters.ContainsKey("ReplaceList"))
            {
                $parameter["apply_to_apps"] = @{"replace_list" = $($ReplaceList)}
            }
            if($PSBoundParameters.ContainsKey("UnassignList"))
            {
                $parameter["apply_to_apps"] = @{"unassign_list" = $($UnassignList)}
            }
            if($PSBoundParameters.ContainsKey("ApplyGroupPolicyList"))
            {
                $parameter["apply_to_groups_in_apps"] = @{"apply_group_policy_list" = $($ApplyGroupPolicyList)}
            }
            if($PSBoundParameters.ContainsKey("GroupPolicyApplyOrder"))
            {
                $parameter["apply_to_groups_in_apps"] = @{"group_policy_apply_order" = $($GroupPolicyApplyOrder)}
            }
            if($PSBoundParameters.ContainsKey("ReplaceGroupPolicyList"))
            {
                $parameter["apply_to_groups_in_apps"] = @{"replace_group_policy_list" = $($ReplaceGroupPolicyList)}
            }
            if($PSBoundParameters.ContainsKey("UnassignGroupPolicyList"))
            {
                $parameter["apply_to_groups_in_apps"] = @{"unassign_group_policy_list" = $($UnassignGroupPolicyList)}
            }
            if($PSBoundParameters.ContainsKey("AnonymousAccessBehavior"))
            {
                $parameter["sections"] = @{
                    "anonymous_networks" = @{
                        "anonymous_access_behavior" = $($AnonymousAccessBehavior)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("AllowedAuthList"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "allowed_auth_list" = @($($AllowedAuthList))
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("AutoRetrySms"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "auto-retry-sms" = $($AutoRetrySms)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BlockedAuthList"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "blocked_auth_list" = $($BlockedAuthList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequireVerifiedPush"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "require_verified_push" = $($RequireVerifiedPush)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequireVerifiedPush"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "verified_push_digits" = $($RequireVerifiedPush)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("VerifiedPushDigits"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "verified_push_digits" = $($VerifiedPushDigits)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("UserAuthBehavior"))
            {
                $parameter["sections"] = @{
                    "authentication_policy" = @{
                        "user_auth_behavior" = $($UserAuthBehavior)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("NoMfaRequiredIpList"))
            {
                $parameter["sections"] = @{
                    "authorized_networks" = @{
                        "no_2fa_required" = @{
                            "ip_list" = $($NoMfaRequiredIpList)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequireEnrollment"))
            {
                $parameter["sections"] = @{
                    "authorized_networks" = @{
                        "no_2fa_required" = @{
                            "require_enrollment" = $($RequireEnrollment)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("MfaRequiredIpList"))
            {
                $parameter["sections"] = @{
                    "authorized_networks" = @{
                        "mfa_required" = @{
                            "ip_list" = $($MfaRequiredIpList)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("DenyOtherAccess"))
            {
                $parameter["sections"] = @{
                    "authorized_networks" = @{
                        "deny_other_access" = $($DenyOtherAccess)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("AllowedBrowsersList"))
            {
                $parameter["sections"] = @{
                    "browsers" = @{
                        "allowed_browsers_list" = $($AllowedBrowsersList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BlockedBrowsersList"))
            {
                $parameter["sections"] = @{
                    "browsers" = @{
                        "blocked_browsers_list" = $($BlockedBrowsersList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("OutOfDateBehavior"))
            {
                $parameter["sections"] = @{
                    "browsers" = @{
                        "out_of_date_behavior" = $($OutOfDateBehavior)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserMaxOutOfDateDays"))
            {
                $parameter["sections"] = @{
                    "browsers" = @{
                        "browser_max_ood_days" = $($BrowserMaxOutOfDateDays)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequiresDha"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "requires_DHA" = $($RequiresDha)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("PromptToInstallDha"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "prompt_to_install" = $($PromptToInstallDha)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("EnforceFirewall"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "enforce_firewall" = $($EnforceFirewall)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("EnforceEncryption"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "enforce_encryption" = $($EnforceEncryption)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("EnforceSystemPassword"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "enforce_system_password" = $($EnforceSystemPassword)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("MacOsEndpointSecurityList"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "macos_endpoint_security_list" = $($MacOsEndpointSecurityList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("MacOsRemediationNote"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "macos_remediation_note" = $($MacOsRemediationNote)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("WindowsEndpointSecurityList"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "windows_endpoint_security_list" = $($WindowsEndpointSecurityList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("WindowsRemediationNote"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "windows_remediation_note" = $($WindowsRemediationNote)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequireDuoAppUpdates"))
            {
                $parameter["sections"] = @{
                    "duo_mobile_app" = @{
                        "require_updates" = $($RequireDuoAppUpdates)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequiresFullDiskEncryption"))
            {
                $parameter["sections"] = @{
                    "full_disk_encryption" = @{
                        "require_encryption" = $($RequiresFullDiskEncryption)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequiresMobileDeviceBiometrics"))
            {
                $parameter["sections"] = @{
                    "mobile_device_biometrics" = @{
                        "require_biometrics" = $($RequiresMobileDeviceBiometrics)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("NewUserBehavior"))
            {
                $parameter["sections"] = @{
                    "new_user" = @{
                        "new_user_behavior" = $($NewUserBehavior)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("AllowUnrestrictedOsList"))
            {
                $parameter["sections"] = @{
                    "operating_systems" = @{
                        "allow_unrestricted_os_list" = $($AllowUnrestrictedOsList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BlockOsList"))
            {
                $parameter["sections"] = @{
                    "operating_systems" = @{
                        "block_os_list" = $($BlockOsList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("OperatingSystemToRestrict"))
            {
                [hashtable]$OsRestrictions = @{}
                if($PSBoundParameters.ContainsKey("OsWarnPolicy"))
                {
                    $OsRestrictions["warn_policy"] = $OsWarnPolicy
                }
                if($PSBoundParameters.ContainsKey("OsWarnVersion"))
                {
                    $OsRestrictions["warn_version"] = $OsWarnVersion
                }
                if($PSBoundParameters.ContainsKey("OsWarnRemediationDays"))
                {
                    $OsRestrictions["warn_remediation_days"] = $OsWarnRemediationDays
                }
                if($PSBoundParameters.ContainsKey("OsBlockPolicy"))
                {
                    $OsRestrictions["block_policy"] = $OsBlockPolicy
                }
                if($PSBoundParameters.ContainsKey("OsBlockVersion"))
                {
                    $OsRestrictions["block_version"] = $OsBlockVersion
                }
                if($PSBoundParameters.ContainsKey("OsBlockRemediationDays"))
                {
                    $OsRestrictions["block_remediation_days"] = $OsBlockRemediationDays
                }
                $parameter["sections"] = @{
                    "operating_systems" = @{
                        $OperatingSystemToRestrict = @{
                            "os_restrictions" = $OsRestrictions
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("FlashPlugin"))
            {
                $parameter["sections"] = @{
                    "plugins" = @{
                        "flash" = $($FlashPlugin)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("JavaPlugin"))
            {
                $parameter["sections"] = @{
                    "plugins" = @{
                        "java" = $($JavaPlugin)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("JavaMaxOutOfDateDays"))
            {
                $parameter["sections"] = @{
                    "plugins" = @{
                        "java_max_ood_days" = $($JavaMaxOutOfDateDays)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsEnabled"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "enabled" = $($BrowserAppsEnabled)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsRememberMethod"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "remember_method" = $($BrowserAppsRememberMethod)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsUserBasedConfirmPerApp"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "user_based" = @{
                                "confirm_per_app" = $($BrowserAppsUserBasedConfirmPerApp)
                            }
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsUserBasedMaxTimeUnits"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "user_based" = @{
                                "max_time_units" = $($BrowserAppsUserBasedMaxTimeUnits)
                            }
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsUserBasedMaxTimeValue"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "user_based" = @{
                                "max_time_value" = $($BrowserAppsUserBasedMaxTimeValue)
                            }
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsRiskBasedMaxTimeUnits"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "risk_based" = @{
                                "max_time_units" = $($BrowserAppsRiskBasedMaxTimeUnits)
                            }
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsRiskBasedMaxTimeValue"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "risk_based" = @{
                                "max_time_value" = $($BrowserAppsRiskBasedMaxTimeValue)
                            }
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("WindowsLogonEnabled"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "windows_logon" = @{
                            "enabled" = $($WindowsLogonEnabled)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("WindowsLogonMaxTimeUnits"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "windows_logon" = @{
                            "max_time_units" = $($WindowsLogonMaxTimeUnits)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("WindowsLogonMaxTimeValue"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "windows_logon" = @{
                            "max_time_value" = $($WindowsLogonMaxTimeValue)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("LimitToRiskBasedAuthMethods"))
            {
                $parameter["sections"] = @{
                    "risk_based_factor_selection" = @{
                        "limit_to_risk_based_auth_methods" = $($LimitToRiskBasedAuthMethods)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RiskBasedVerifiedPushDigits"))
            {
                $parameter["sections"] = @{
                    "risk_based_factor_selection" = @{
                        "risk_based_verified_push_digits" = $($RiskBasedVerifiedPushDigits)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequiresScreenLock"))
            {
                $parameter["sections"] = @{
                    "screen_lock" = @{
                        "require_screen_lock" = $($RequiresScreenLock)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BlockTamperedDevices"))
            {
                $parameter["sections"] = @{
                    "tampered_devices" = @{
                        "block_tampered_devices" = $($BlockTamperedDevices)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("TrustedEndpointChecking"))
            {
                $parameter["sections"] = @{
                    "trusted_endpoints" = @{
                        "trusted_endpoint_checking" = $($TrustedEndpointChecking)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("CiscoSecureEndpointCanBlock"))
            {
                $parameter["sections"] = @{
                    "trusted_endpoints" = @{
                        "cisco_secure_endpoint_can_block" = $($CiscoSecureEndpointCanBlock)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("TrustedEndpointCheckingMobile"))
            {
                $parameter["sections"] = @{
                    "trusted_endpoints" = @{
                        "trusted_endpoint_checking_mobile" = $($TrustedEndpointCheckingMobile)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequireMfaCountriesList"))
            {
                $parameter["sections"] = @{
                    "user_location" = @{
                        "require_mfa_countries_list" = $($RequireMfaCountriesList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("DenyAccessCountriesList"))
            {
                $parameter["sections"] = @{
                    "user_location" = @{
                        "deny_access_countries_list" = $($DenyAccessCountriesList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("AllowAccessNoMfaCountriesList"))
            {
                $parameter["sections"] = @{
                    "user_location" = @{
                        "allow_access_no_2fa_countries_list" = $($AllowAccessNoMfaCountriesList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("IgnoreLocationCountriesList"))
            {
                $parameter["sections"] = @{
                    "user_location" = @{
                        "ignore_location_countries_list" = $($IgnoreLocationCountriesList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("DefaultAction"))
            {
                $parameter["sections"] = @{
                    "user_location" = @{
                        "default_action" = $($DefaultAction)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("Description"))
            {
                $parameter["desc"] = "$($Description)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoPolicy.ps1' 1177
#Region './Public/New-DuoUser.ps1' -1

function New-DuoUser {
    <#
    .SYNOPSIS
    Create a new user with the specified username

    .DESCRIPTION
    Create a new user with the specified username

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER Username
    The name of the user to create

    .PARAMETER Email
    The email address of this user.

    .PARAMETER FullName
    The real name (or full name) of this user

    .PARAMETER Status
    The user's status. Allowed Values "active","bypass","disabled"
    "active" The user must complete secondary authentication. This is the default value if no status is specified.
    "bypass" The user will bypass secondary authentication after completing primary authentication.
    "disabled" The user will not be able to complete secondary authentication.

    .PARAMETER FirstName
    The user's given name.

    .PARAMETER LastName
    The user's surname

    .PARAMETER Notes
    An optional description or notes field. Can be viewed in the Duo Admin Panel

    .PARAMETER Alias
    Username aliases for the user. Up to four aliases may be specified with this parameter.
    Aliases must be unique amongst users

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.
    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Add-DuoUser -ApiHostname $ApiHostname -Username 'bob' -Email 'bob@example.com' -Status 'active' -Alias 'admin' -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Username,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Email,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$FullName,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("active", "bypass","disabled")]
        [string]$Status,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$FirstName,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$LastName,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Notes,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [string[]]$Alias,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Username, "Create new user"))
        {
            [string]$apiPath = '/admin/v1/users'
            if($PSBoundParameters.ContainsKey("Username"))
            {
                $parameter["username"] = "$($Username)"
            }
            if($PSBoundParameters.ContainsKey("Email"))
            {
                $parameter["email"] = "$($Email)"
            }
            if($PSBoundParameters.ContainsKey("FullName"))
            {
                $parameter["realname"] = "$($FullName)"
            }
            if($PSBoundParameters.ContainsKey("Status"))
            {
                $parameter["status"] = "$($Status)"
            }
            if($PSBoundParameters.ContainsKey("FirstName"))
            {
                $parameter["firstname"] = "$($FirstName)"
            }
            if($PSBoundParameters.ContainsKey("LastName"))
            {
                $parameter["lastname"] = "$($LastName)"
            }
            if($PSBoundParameters.ContainsKey("Notes"))
            {
                $parameter["notes"] = "$($Notes)"
            }
            if($PSBoundParameters.ContainsKey("Alias"))
            {
                [string]$string = ""
                for ($i = 0; $i -lt $Alias.count; $i ++)
                {
                    $string += "alias$($i+1)=$($Alias[$i])&"
                }

                $parameter["aliases"] = "$($string.ToString() -replace '&$','')"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/New-DuoUser.ps1' 151
#Region './Public/Remove-DuoAccount.ps1' -1

function Remove-DuoAccount {
    <#
    .SYNOPSIS
    Remove Child Account

    .DESCRIPTION
    Remove Child Account

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoAccount -ApiHostname $ApiHostname -GroupId 'FAHS9D8FA9SDF8A9' -Credential $Credential -AccountId 'JF0ASD98F0ASD89UFA'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($GroupId, "Remove Child Account"))
        {
            [string]$apiPath = "/accounts/v1/account/delete"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoAccount.ps1' 59
#Region './Public/Remove-DuoAdministrativeUnit.ps1' -1

function Remove-DuoAdministrativeUnit {
    <#
    .SYNOPSIS
    Remove member from administrative unit

    .DESCRIPTION
    Remove member from administrative unit

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER AdministrativeUnitId
    Target administrative unit ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoAdministrativeUnit -ApiHostname $ApiHostname -Credential $Credential -AdministrativeUnitId 'AJ0SDF8ASU0DF8'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministrativeUnitId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Remove admin unit"))
        {
            [string]$apiPath = "/admin/v1/administrative_units/$($AdministrativeUnitId)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoAdministrativeUnit.ps1' 66
#Region './Public/Remove-DuoAdministrativeUnitMember.ps1' -1

function Remove-DuoAdministrativeUnitMember {
    <#
    .SYNOPSIS
    Remove member from administrative unit

    .DESCRIPTION
    Remove member from administrative unit

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER AdministrativeUnitId
    Target administrative unit ID

    .PARAMETER AdministratorId
    target administrator ID

    .PARAMETER GroupId
    target group ID

    .PARAMETER IntegrationKey
    Target integration key

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoAdministrativeUnitMember -ApiHostname $ApiHostname -Credential $Credential -GroupId '0AUSF8DF9A7S6DF98AS' -AdministrativeUnitId 'AJ0SDF8ASU0DF8'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High", DefaultParameterSetName = "A")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="A")]
        [Parameter(ParameterSetName="B")]
        [Parameter(ParameterSetName="C")]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="A")]
        [Parameter(ParameterSetName="B")]
        [Parameter(ParameterSetName="C")]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="A")]
        [Parameter(ParameterSetName="B")]
        [Parameter(ParameterSetName="C")]
        [string]$AdministrativeUnitId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="A")]
        [Parameter(ParameterSetName="B")]
        [Parameter(ParameterSetName="C")]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="A")]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="B")]
        [string]$GroupId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName="C")]
        [string]$IntegrationKey
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Remove member from admin unit"))
        {

            switch ($PSCmdlet.ParameterSetName) {
                "A" {[string]$apiPath = "/admin/v1/administrative_units/$($AdministrativeUnitId)/admin/$($AdministratorId)"}
                "B" {[string]$apiPath = "/admin/v1/administrative_units/$($AdministrativeUnitId)/group/$($GroupId)"}
                "C" {[string]$apiPath = "/admin/v1/administrative_units/$($AdministrativeUnitId)/integration/$($IntegrationKey)"}
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoAdministrativeUnitMember.ps1' 104
#Region './Public/Remove-DuoAdministrator.ps1' -1

function Remove-DuoAdministrator {
    <#
    .SYNOPSIS
    Remove Administrator

    .DESCRIPTION
    Remove Administrator

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER AdministratorId
    Target Administrator ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoAdministrator -ApiHostname $ApiHostname -AdministratorId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($AdministratorId, "Remove Administrator"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoAdministrator.ps1' 65
#Region './Public/Remove-DuoAdministratorActivationLink.ps1' -1

function Remove-DuoAdministratorActivationLink {
    <#
    .SYNOPSIS
    eletes and invalidates the current activation link from the administrator pending activation

    .DESCRIPTION
    eletes and invalidates the current activation link from the administrator pending activation

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER AdministratorId
    Target Administrator ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoAdministratorActivationLink -ApiHostname $ApiHostname -AdministratorId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($AdministratorId, "Deletes and invalidates the current activation link from the administrator"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)/activation_link"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoAdministratorActivationLink.ps1' 65
#Region './Public/Remove-DuoAdministratorPendingActivation.ps1' -1

function Remove-DuoAdministratorPendingActivation {
    <#
    .SYNOPSIS
    Delete the pending admin activation

    .DESCRIPTION
    Delete the pending admin activation

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER AdministratorActivationId
    Target Administrator Activation ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoAdministrator -ApiHostname $ApiHostname -AdministratorActivationId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorActivationId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($AdministratorActivationId, "Delete the pending admin activation"))
        {
            [string]$apiPath = "/admin/v1/admins/activations/$($AdministratorActivationId)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoAdministratorPendingActivation.ps1' 65
#Region './Public/Remove-DuoBypassCode.ps1' -1

function Remove-DuoBypassCode {
    <#
    .SYNOPSIS
    Remove bypass code from the system

    .DESCRIPTION
    Remove bypass code from the system

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER BypassCodeId
    Target Bypass code ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoBypassCode -ApiHostname $ApiHostname -BypassCodeId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$BypassCodeId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($BypassCodeId, "Remove bypass code from the system"))
        {
            [string]$apiPath = "/admin/v1/bypass_codes/$($BypassCodeId)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoBypassCode.ps1' 65
#Region './Public/Remove-DuoGroup.ps1' -1

function Remove-DuoGroup {
    <#
    .SYNOPSIS
    Remove Group

    .DESCRIPTION
    Remove Group

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER GroupId
    Target Group ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoGroup -ApiHostname $ApiHostname -GroupId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$GroupId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($GroupId, "Remove Group"))
        {
            [string]$apiPath = "/admin/v1/groups/$($GroupId)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoGroup.ps1' 65
#Region './Public/Remove-DuoHardwareToken.ps1' -1

function Remove-DuoHardwareToken {
    <#
    .SYNOPSIS
    Remove user `

    .DESCRIPTION
    Remove user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER TokenId
    Target User ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoHardwareToken -ApiHostname $ApiHostname -TokenId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(`
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$TokenId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($TokenId, "Remove token"))
        {
            [string]$apiPath = "/admin/v1/token/$($TokenId)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoHardwareToken.ps1' 66
#Region './Public/Remove-DuoHardwareTokenFromUser.ps1' -1

function Remove-DuoHardwareTokenFromUser {
    <#
    .SYNOPSIS
    Disassociate a token from the user

    .DESCRIPTION
    Disassociate a token from the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .PARAMETER TokenId
    Target token ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoHardwareTokenFromUser -ApiHostname $ApiHostname -Credential $Credential -UserId '0AUSF8DF9A7S6DF98AS' -TokenId 'AJ0SDF8ASU0DF8' -AccountId 'SD0AF870ADSF70ASG'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$TokenId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Remove token from user"))
        {
            [string]$apiPath = "/admin/v1/users/$($UserId)/tokens/$($TokenId)"

            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoHardwareTokenFromUser.ps1' 73
#Region './Public/Remove-DuoIntegration.ps1' -1

function Remove-DuoIntegration {
    <#
    .SYNOPSIS
    Remove integration

    .DESCRIPTION
    Remove integration

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER Key
    Target integration key

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoIntegration -ApiHostname $ApiHostname -Key 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Key,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($Key, "Remove integration"))
        {
            [string]$apiPath = "/admin/v1/integrations/$($Key)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoIntegration.ps1' 65
#Region './Public/Remove-DuoLogo.ps1' -1

function Remove-DuoLogo {
    <#
    .SYNOPSIS
    Remove Logo

    .DESCRIPTION
    Remove Logo

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoLogo -ApiHostname $ApiHostname -GroupId 'FAHS9D8FA9SDF8A9' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($GroupId, "Remove Logo"))
        {
            [string]$apiPath = "/admin/v1/logo"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoLogo.ps1' 59
#Region './Public/Remove-DuoPhone.ps1' -1

function Remove-DuoPhone {
    <#
    .SYNOPSIS
    Remove Phone

    .DESCRIPTION
    Remove Phone

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER PhoneId
    Target Phone ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoPhone -ApiHostname $ApiHostname -PhoneId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$PhoneId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($PhoneId, "Remove Phone"))
        {
            [string]$apiPath = "/admin/v1/phones/$($PhoneId)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoPhone.ps1' 65
#Region './Public/Remove-DuoPhoneFromUser.ps1' -1

function Remove-DuoPhoneFromUser {
    <#
    .SYNOPSIS
    Disassociate a phone from the user

    .DESCRIPTION
    Disassociate a phone from the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .PARAMETER PhoneId
    Target phone ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoPhoneFromUser -ApiHostname $ApiHostname -Credential $Credential -UserId '0AUSF8DF9A7S6DF98AS' -PhoneId 'AJ0SDF8ASU0DF8' -AccountId 'SD0AF870ADSF70ASG'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$PhoneId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Remove phone from user"))
        {
            [string]$apiPath = "/admin/v1/users/$($UserId)/phones/$($PhoneId)"

            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoPhoneFromUser.ps1' 73
#Region './Public/Remove-DuoPolicy.ps1' -1

function Remove-DuoPolicy {
    <#
    .SYNOPSIS
    Remove Policy

    .DESCRIPTION
    Remove Policy

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER PolicyKey
    Target PolicyKey

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoPolicy -ApiHostname $ApiHostname -PolicyKey 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$PolicyKey,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($PolicyKey, "Remove Group"))
        {
            [string]$apiPath = "/admin/v2/policies/$($PolicyKey)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoPolicy.ps1' 65
#Region './Public/Remove-DuoUser.ps1' -1

function Remove-DuoUser {
    <#
    .SYNOPSIS
    Remove user

    .DESCRIPTION
    Remove user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER UserId
    Target User ID

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoUser -ApiHostname $ApiHostname -UserId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Remove user"))
        {
            [string]$apiPath = "/admin/v1/users/$($UserId)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoUser.ps1' 66
#Region './Public/Remove-DuoUserFromGroup.ps1' -1

function Remove-DuoUserFromGroup {
    <#
    .SYNOPSIS
    Disassociate a group from the user

    .DESCRIPTION
    Disassociate a group from the user

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .PARAMETER GroupId
    Target Group ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoUserFromGroup -ApiHostname $ApiHostname -Credential $Credential -UserId '0AUSF8DF9A7S6DF98AS' -GroupId 'AJ0SDF8ASU0DF8' -AccountId 'SD0AF870ADSF70ASG'
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$GroupId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Remove user from group"))
        {
            [string]$apiPath = "/admin/v1/users/$($UserId)/groups/$($GroupId)"

            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoUserFromGroup.ps1' 73
#Region './Public/Remove-DuoWebAuthnCredential.ps1' -1

function Remove-DuoWebAuthnCredential {
    <#
    .SYNOPSIS
    Delete the WebAuthn credential from the system

    .DESCRIPTION
    Delete the WebAuthn credential from the system

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER Key
    Target Key

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Remove-DuoWebAuthnCredential -ApiHostname $ApiHostname -Key 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Key,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($Key, "Remove Webauthn Credential"))
        {
            [string]$apiPath = "/admin/v1/groups/$($Key)"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method DELETE -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Remove-DuoWebAuthnCredential.ps1' 65
#Region './Public/Reset-DuoAdministratorAuthenticatinAttempt.ps1' -1

function Reset-DuoAdministratorAuthenticatinAttempt {
    <#
    .SYNOPSIS
    Clear the number of failed login attempts for the administrator.
    Re-enables an administrator who has been disabled due to too many failed authentication attempts

    .DESCRIPTION
    Clear the number of failed login attempts for the administrator.
    Re-enables an administrator who has been disabled due to too many failed authentication attempts

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER AdministratorId
    Target Administrator ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Reset-DuoAdministratorAuthenticatinAttempt -ApiHostname $ApiHostname -AdministratorId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($AdministratorId, "Clear the number of failed login attempts for the administrator"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)/reset"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Reset-DuoAdministratorAuthenticatinAttempt.ps1' 67
#Region './Public/Send-DuoAdministratorActivationLink.ps1' -1

function Send-DuoAdministratorActivationLink {
    <#
    .SYNOPSIS
    Email the current activation link to the administrator pending activation with the administrator

    .DESCRIPTION
    Email the current activation link to the administrator pending activation with the administrator

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Username and SKEY as securestring

    .PARAMETER AdministratorId
    Target Administrator ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Send-DuoAdministratorActivationLink -ApiHostname $ApiHostname -AdministratorId 'FAHS9D8FA9SDF8A9' -AccountId 'SFAH9D8FH9AS8DF9AS' -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($AdministratorId, "Email the current activation link to the administrator"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)/activation_link/email"
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Send-DuoAdministratorActivationLink.ps1' 65
#Region './Public/Send-DuoEnrollmentEmail.ps1' -1

function Send-DuoEnrollmentEmail {
    <#
    .SYNOPSIS
    Enroll a user with username and email address and send them an enrollment email

    .DESCRIPTION
    Enroll a user with username and email address and send them an enrollment email

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER Username
    The name of the user to create

    .PARAMETER Email
    The email address of this user.

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>$user = @{
        ApiHostname = $ApiHostname
        Username = 'bob'
        Email = 'bob@example.com'
        Credential = $Credential
        AccountId = "AALSFLAJFKS5AJLKDJ55LA5KS"
    }
    PS>Send-DuoEnrollmentEmail @user
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Username,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Email,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Username, "Enroll a user"))
        {
            [string]$apiPath = '/admin/v1/users/enroll'
            if($PSBoundParameters.ContainsKey("Username"))
            {
                $parameter["username"] = "$($Username)"
            }
            if($PSBoundParameters.ContainsKey("Email"))
            {
                $parameter["email"] = "$($Email)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Send-DuoEnrollmentEmail.ps1' 87
#Region './Public/Send-DuoSmsPhoneActivationCode.ps1' -1

function Send-DuoSmsPhoneActivationCode {
    <#
    .SYNOPSIS
    Generate a Duo Mobile activation code and send it to the phone via SMS, optionally sending an additional message with a URL to install Duo Mobile. This method will fail if the phone's type or platform are Unknown.

    .DESCRIPTION
    Generate a Duo Mobile activation code and send it to the phone via SMS, optionally sending an additional message with a URL to install Duo Mobile. This method will fail if the phone's type or platform are Unknown.

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER PhoneId
    Target Phone ID

    .PARAMETER ValidSeconds
    The number of seconds this activation code remains valid. Default: 86400 (one day). Expiration not supported for legacy phone platforms that support passcode generation only (not Duo Push).

    .PARAMETER SendInstallUrl
    Specify to also send an installation URL for Duo Mobile

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Send-DuoSmsPhoneActivationCode -ApiHostname $ApiHostname -ValidSeconds 3600 -SendInstallUrl -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$PhoneId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$ValidSeconds,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$SendInstallUrl,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Send Activation Code"))
        {
            [string]$apiPath = "/admin/v1/phones/$($PhoneId)/send_sms_activation"
            if($PSBoundParameters.ContainsKey("ValidSeconds"))
            {
                $parameter["valid_sec"] = $ValidSeconds
            }
            if($PSBoundParameters.ContainsKey("SendInstallUrl"))
            {
                $parameter["install"] = 1
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Send-DuoSmsPhoneActivationCode.ps1' 86
#Region './Public/Send-DuoSmsPhonePasscode.ps1' -1

function Send-DuoSmsPhonePasscode {
    <#
    .SYNOPSIS
    Generate a Duo Mobile activation code and send it to the phone via SMS, optionally sending an additional message with a URL to install Duo Mobile. This method will fail if the phone's type or platform are Unknown.

    .DESCRIPTION
    Generate a Duo Mobile activation code and send it to the phone via SMS, optionally sending an additional message with a URL to install Duo Mobile. This method will fail if the phone's type or platform are Unknown.

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER PhoneId
    Target Phone ID

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Send-DuoSmsPhonePasscode -ApiHostname $ApiHostname -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$PhoneId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Send Activation Code"))
        {
            [string]$apiPath = "/admin/v1/phones/$($PhoneId)/send_sms_passcodes"
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Send-DuoSmsPhonePasscode.ps1' 64
#Region './Public/Sync-DuoAdministratorFromDirectory.ps1' -1

function Sync-DuoAdministratorFromDirectory {
    <#
    .SYNOPSIS
    Initiate a sync to create, update, or mark for deletion the user specified against the directory specified

    .DESCRIPTION
    Initiate a sync to create, update, or mark for deletion the user specified against the directory specified

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER EmailAddress
    The email of the user

    .PARAMETER DirectoryKey
    The DirectoryKey

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Sync-DuoAdministratorFromDirectory -ApiHostname $ApiHostname -EmailAddress 'bob@axample.com' -DirectoryKey "AS09FAUS0DA" -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$EmailAddress,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$DirectoryKey,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($EmailAddress, "Sync admin from directory"))
        {
            [string]$apiPath = "/admin/v1/admins/directorysync/$($DirectoryKey)/syncadmin"
            if($PSBoundParameters.ContainsKey("Username"))
            {
                $parameter["email"] = "$($EmailAddress)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Sync-DuoAdministratorFromDirectory.ps1' 75
#Region './Public/Sync-DuoHardwareToken.ps1' -1

function Sync-DuoHardwareToken {
    <#
    .SYNOPSIS
    Create a new toekn

    .DESCRIPTION
    Create a new toekn

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER TokenId
    Target Token ID

    .PARAMETER Code1
    The first code from the token

    .PARAMETER Code2
    The second code from the token

    .PARAMETER Code3
    The third code from the token

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Sync-DuoHardwareToken -TokenId 'F8S09AD8F0AS' -Code1 '2134145' -Code2 '324134' -Code3 '023984023' -ApiHostname $ApiHostname -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$TokenId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Code1,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Code2,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Code3,


        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Code1, "Resync Tokens"))
        {
            [string]$apiPath = "/admin/v1/toekns/$($TokenId)/resync"
            if($PSBoundParameters.ContainsKey("Code1"))
            {
                $parameter["code1"] = "$($Code1)"
            }
            if($PSBoundParameters.ContainsKey("Code2"))
            {
                $parameter["code2"] = "$($Code2)"
            }
            if($PSBoundParameters.ContainsKey("Code3"))
            {
                $parameter["code3"] = "$($Code3)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Sync-DuoHardwareToken.ps1' 97
#Region './Public/Sync-DuoUserFromDirectory.ps1' -1

function Sync-DuoUserFromDirectory {
    <#
    .SYNOPSIS
    Initiate a sync to create, update, or mark for deletion the user specified against the directory specified

    .DESCRIPTION
    Initiate a sync to create, update, or mark for deletion the user specified against the directory specified

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER Username
    The name of the user to create

    .PARAMETER DirectoryKey
    The DirectoryKey

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Sync-DuoUserFromDirectory -ApiHostname $ApiHostname -Username 'bob' -DirectoryKey 'SADF879DSF89FA' -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Username,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$DirectoryKey,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Username, "Sync user from directory"))
        {
            [string]$apiPath = "/admin/v1/users/directorysync/$($DirectoryKey)/syncuser"
            if($PSBoundParameters.ContainsKey("Username"))
            {
                $parameter["username"] = "$($Username)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Sync-DuoUserFromDirectory.ps1' 76
#Region './Public/Update-DuoAdministrativeUnit.ps1' -1

function Update-DuoAdministrativeUnit {
    <#
    .SYNOPSIS
    Update administrative unit

    .DESCRIPTION
    Update administrative unit

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER Name
    The name of the new administrative unit. Must be unique amongst all administrative units.

    .PARAMETER Description
    A description of the new administrative unit.

    .PARAMETER RestrictByGroups
    Does the new administrative unit specify groups? Default: false

    .PARAMETER RestrictByIntegrations
    Does the new administrative unit specify integrations? Default: false.

    .PARAMETER AdministratorIds
    One or more admin_id values to assign administrators to the new administrative unit.
    The administrator user must have restricted_by_admin_units set to true before attempting to assign them to an administrative unit via the API.

    .PARAMETER GroupIds
    One or more group_id values to assign groups to the new administrative unit.

    .PARAMETER IntegrationKeys
    One or more integration_key values to assign integrations to the new administrative unit.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Update-DuoAdministrativeUnit -Name "MyUnit" -Description "New unit" -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministrativeUnitId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Description,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RestrictByGroups,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RestrictByIntegrations,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$AdministratorIds,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$GroupIds,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$IntegrationKeys

    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Update admin unit"))
        {
            [string]$apiPath = "/admin/v1/administrative_unit/$($AdministrativeUnitId)"

            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = $($Name)
            }
            if($PSBoundParameters.ContainsKey("Description"))
            {
                $parameter["description"] = $($Description)
            }
            if($PSBoundParameters.ContainsKey("RestrictByGroups"))
            {
                $parameter["restrict_by_groups"] = $($RestrictByGroups)
            }
            if($PSBoundParameters.ContainsKey("RestrictByIntegrations"))
            {
                $parameter["restrict_by_integrations"] = $($RestrictByIntegrations)
            }
            if($PSBoundParameters.ContainsKey("AdministratorIds"))
            {
                $parameter["admins"] = $($AdministratorIds)
            }
            if($PSBoundParameters.ContainsKey("GroupIds"))
            {
                $parameter["groups"] = $($GroupIds)
            }
            if($PSBoundParameters.ContainsKey("IntegrationKeys"))
            {
                $parameter["integrations"] = $($IntegrationKeys)
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Update-DuoAdministrativeUnit.ps1' 136
#Region './Public/Update-DuoAdministrator.ps1' -1

function Update-DuoAdministrator {
    <#
    .SYNOPSIS
    Update an administrator

    .DESCRIPTION
    Update an administrator

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER Name
    Name for the new administrator.

    .PARAMETER EmailAddress
    Valid email address for the new administrator.

    .PARAMETER PhoneNumber
    Phone number for the new administrator; E.164 format recommended (i.e. "+17345551212"). If no leading plus sign is provided then it is assumed to be a United States number and an implicit "+1" country code is prepended
    If this parameter is specified it cannot be empty.

    .PARAMETER Role
    The administrator's role.
    One of: "Owner", "Administrator", "Application Manager", "User Manager", "Help Desk", "Billing", "Phishing Manager", or "Read-only".
    The role names are case-sensitive. Defaults to "Owner" if not specified.

    .PARAMETER RestrictedByAdminUnits
    s this administrator restricted by an administrative unit assignment? Either true or false. Defaults to false if not specified.
    Must be set to true in order to add the admin to an administrative unit using the API.
    Note that attempting to set to true for admins with the "Owner" role results in a failure response.

    .PARAMETER SendEmail
    If set to $true, the activation link and an introductory message will be emailed to the new administrator. If set to $false, no email is sent, and the link is returned to the API method's caller only. Default: $false.

    .PARAMETER TokenId
    The token_id of the hardware token to associate with the administrator.

    .PARAMETER ValidDays
    Number of days before the activation link expires. Default: 7 Maximum:: 31

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Update-DuoAdministrator -AdministratorId "AS0DF9AS0FU0ASF" -Role "Read-only" -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$EmailAddress,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateScript({
            if($PSItem -inotmatch '^(\+|\d)(\d+){8,12}$')
            {
                throw "Phone Number must be in E.164 Format. i.e. '+17345551212'. If no leading plus sign is provided then it is assumed to be a United States number and an implicit '+1' country code is prepended"
            }
            return $true
        })]
        [string]$PhoneNumber,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("Owner", "Administrator", "Application Manager", "User Manager", "Help Desk", "Billing", "Phishing Manager", "Read-only")]
        [string]$Role,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RestrictedByAdminUnits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$SendEmail,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$TokenId,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(7,30)]
        [int]$ValidDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Update administrator"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)"
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("EmailAddress"))
            {
                $parameter["email"] = "$($EmailAddress)"
            }
            if($PSBoundParameters.ContainsKey("PhoneNumber"))
            {
                $parameter["phone"] = "$($PhoneNumber)"
            }
            if($PSBoundParameters.ContainsKey("Role"))
            {
                $parameter["role"] = "$($Role)"
            }
            if($PSBoundParameters.ContainsKey("RestrictedByAdminUnits"))
            {
                $parameter["restricted_by_admin_units"] = $($RestrictedByAdminUnits)
            }
            if($PSBoundParameters.ContainsKey("SendEmail"))
            {
                $parameter["send_email"] = 1
            }
            if($PSBoundParameters.ContainsKey("TokenId"))
            {
                $parameter["token_id"] = "$($TokenId)"
            }
            if($PSBoundParameters.ContainsKey("ValidDays"))
            {
                $parameter["valid_days"] = $ValidDays
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Update-DuoAdministrator.ps1' 157
#Region './Public/Update-DuoAdministratorExternalPasswordStatus.ps1' -1

function Update-DuoAdministratorExternalPasswordStatus {
    <#
    .SYNOPSIS
    Update an administrator

    .DESCRIPTION
    Update an administrator

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AdministratorId
    Target admin ID

    .PARAMETER EnableExternalPasswordMgmt
    Specify true if the administrator's password may be set via API, or false if passwords are self-managed. If specifying true you may also send a password value in the same operation

    .PARAMETER Password
    New password for the administrator. May be sent in the same operation with EnableExternalPasswordMgmt=true

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Update-DuoAdministratorExternalPasswordStatus -AdministratorId "AS0DF9AS0FU0ASF" -Role "Read-only" -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AdministratorId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$EnableExternalPasswordMgmt,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [securestring]$Password = $(if(-not($EnableExternalPasswordMgmt)){throw "'EnableExternalPasswordMgmt' must be set to True"}),

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Update administrator"))
        {
            [string]$apiPath = "/admin/v1/admins/$($AdministratorId)"
            if($PSBoundParameters.ContainsKey("EnableExternalPasswordMgmt"))
            {
                $parameter["has_external_password_mgmt"] = "$($EnableExternalPasswordMgmt)"
            }
            if($PSBoundParameters.ContainsKey("Password"))
            {
                $passwd = [pscredential]::new($AdministratorId,$Password)
                $parameter["password"] = $($passwd.GetNetworkCredential().Password)
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Update-DuoAdministratorExternalPasswordStatus.ps1' 87
#Region './Public/Update-DuoGroup.ps1' -1

function Update-DuoGroup {
    <#
    .SYNOPSIS
    Update a group

    .DESCRIPTION
    Update a group

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER Name
    The name of the group to create

    .PARAMETER Status
    The user's status. Allowed Values "active","bypass","disabled"
    "active" The user must complete secondary authentication. This is the default value if no status is specified.
    "bypass" The user will bypass secondary authentication after completing primary authentication.
    "disabled" The user will not be able to complete secondary authentication.

    .PARAMETER Description
    An optional description

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER GroupId
    Target group ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Update-DuoGroup -ApiHostname $ApiHostname -Name 'MyNewGroupName' -Status 'active' -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$GroupId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("active", "bypass","disabled")]
        [string]$Status,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Description,


        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($GroupId,"Update group"))
        {
            [string]$apiPath = "/admin/v1/groups/$($GroupId)"
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("Status"))
            {
                $parameter["status"] = "$($Status)"
            }
            if($PSBoundParameters.ContainsKey("Description"))
            {
                $parameter["desc"] = "$($Description)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Update-DuoGroup.ps1' 101
#Region './Public/Update-DuoIntegration.ps1' -1

function Update-DuoIntegration {
    <#
    .SYNOPSIS
    Update integration.

    .DESCRIPTION
    Update integration.

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring



    .PARAMETER Name
    The name of the integration to create

    .PARAMETER Type
    The type of integration to create
    Allowed values: "1password","accountsapi","adfs","adminapi","aeries","agadobe_documentcloud","agaha","agasana","agaws","agatlassian-cloud","agbamboohr","agbarracuda-waf","agbluejeans","agbomgar","agbonusly","agbox","agbugsnag","agcanvas","agciscoasa","agclarizen","agcloudlock","agconfluence","agcrashplan","agcyberark","agdatadog","agdesk","agdigicert","agdng","agdocusign","agdropbox","agduo-adminpanel","agegnyte","agevernote","agexpensify","agfacebook","agfreshdesk","aggeneric","aggithub-business","aggithub-enterprise","aggoogle","aggotomeeting","aggreenhouse","aghackerone","aghackerrank","agheroku","aghipchat","agigloo","agintacct","agjamf-jss","agjira","agjitbit","aglooker","agmarketo","agmeraki","agmonday","agnamely","agnetdocuments","agnewrelic","agoffice365","agopendns","agpagerduty","agpaloalto-aperture","agpaloalto","agremedyforce","agringcentral","agrobin","agsalesforce","agsamanage","agsaucelabs","agsharefile","agsignalsciences","agslack","agsmartsheet","agstatuspageio","agsugarcrm","agsumologic","agsyncplicity","agtableau-online","agtableau","agudemy","aguservoice","agwebex","agwebex-controlhub","agworkday","agzendesk","agzoom","akamai-eaa","array","aws-directory-service","azure-ca","authapi","barracuda","bitium","bitwarden","bomgar","caradigm","cas","checkpoint","cisco","ciscofirepower","ciscoiseradius","ciscoradius","citrixcag","citrixns","clearpass","confluence","cyberark","cyberarkweb","dag","device","device-management-portal","dng","dng-rdp","dng-smb","dng-ssh","drawbridgenetworks","drupal","epic","f5bigip","f5bigipweb","f5firepass","fortinet","greyheller","huntress","jira","juniper","juniperuac","keeper","labtech","lastpass","ldapproxy","macos","merakiradius","myworkdrive","netmotion","oam","okta","onelogin","openvpn","openvpnas","owa","paloalto","partner_authapi","partner_websdk","pingfederate","portal","radius","rdgateway","rdp","rdweb","resilient","rest","rras","sailpoint","sailpointweb","samlidp","shibboleth","securex-dashboard","sonicwallsra","sophosutm","splunk","thycotic","tmg","uag","unix","verify","vmwareview","websdk","workday","wordpress"

    .PARAMETER AllowAllAdminMethods
    Grant an Admin API integration permission for all Admins methods

    .PARAMETER AllowAccountInfo
    If creating an Admin API integration, set this to grant it permission for all Account Info methods

    .PARAMETER AllowAllAdminIntegrations
    Grant an Admin API integration permission for all Integrations methods

    .PARAMETER AllowAllAdminLogs
    Grant an Admin API integration permission for all Logs methods

    .PARAMETER AllowAllAdminResources
    Grant an Admin API integration permission to retrieve objects like users, phones, and hardware tokens

    .PARAMETER AllowAllAdminSettings
    Grant an Admin API integration permission for all Settings methods

    .PARAMETER AllowAllAdminWriteResources
    Grant an Admin API integration permission to create and modify objects like users, phones, and hardware tokens.

    .PARAMETER PhoneCallGreeting
    Voice greeting read before the authentication instructions to users who authenticate with a phone callback

    .PARAMETER AllowedGrops
    An array of group IDs that are allowed to authenticate with the integration. If empty, all interations are allowed.
    Object limits: 100 interations per integration.

    .PARAMETER AllowNetworks
    An array of IP addresses, IP ranges, or CIDRs specifying the networks allowed to access this API integration. Only applicable to Accounts API and Admin API integrations.
    A given API integration may apply a network restriction to itself via API; use a different API integration to apply the network restriction, or edit the API application in the Duo Admin Panel GUI.

    .PARAMETER Notes
    Description of the integration

    .PARAMETER AllowSelfService
    Grant an integration permission to allow users to manage their own devices. This is only supported by integrations which allow for self service configuration

    .PARAMETER UsernameNormalization
    Policy for whether or not usernames should be altered before trying to match them to a user account.

    .PARAMETER AccountId
    Target Account Id

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Update-DuoIntegration -Name "My Domain rdp" -Type "rdp" -ApiHostname $ApiHostname -Credential $Credential -AllowSelfService

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Update-DuoIntegration -Name "My Domain owa" -Type "owa" -ApiHostname $ApiHostname -Credential $Credential
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$Key,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("1password","accountsapi","adfs","adminapi","aeries","agadobe_documentcloud","agaha","agasana","agaws","agatlassian-cloud","agbamboohr","agbarracuda-waf","agbluejeans","agbomgar","agbonusly","agbox","agbugsnag","agcanvas","agciscoasa","agclarizen","agcloudlock","agconfluence","agcrashplan","agcyberark","agdatadog","agdesk","agdigicert","agdng","agdocusign","agdropbox","agduo-adminpanel","agegnyte","agevernote","agexpensify","agfacebook","agfreshdesk","aggeneric","aggithub-business","aggithub-enterprise","aggoogle","aggotomeeting","aggreenhouse","aghackerone","aghackerrank","agheroku","aghipchat","agigloo","agintacct","agjamf-jss","agjira","agjitbit","aglooker","agmarketo","agmeraki","agmonday","agnamely","agnetdocuments","agnewrelic","agoffice365","agopendns","agpagerduty","agpaloalto-aperture","agpaloalto","agremedyforce","agringcentral","agrobin","agsalesforce","agsamanage","agsaucelabs","agsharefile","agsignalsciences","agslack","agsmartsheet","agstatuspageio","agsugarcrm","agsumologic","agsyncplicity","agtableau-online","agtableau","agudemy","aguservoice","agwebex","agwebex-controlhub","agworkday","agzendesk","agzoom","akamai-eaa","array","aws-directory-service","azure-ca","authapi","barracuda","bitium","bitwarden","bomgar","caradigm","cas","checkpoint","cisco","ciscofirepower","ciscoiseradius","ciscoradius","citrixcag","citrixns","clearpass","confluence","cyberark","cyberarkweb","dag","device","device-management-portal","dng","dng-rdp","dng-smb","dng-ssh","drawbridgenetworks","drupal","epic","f5bigip","f5bigipweb","f5firepass","fortinet","greyheller","huntress","jira","juniper","juniperuac","keeper","labtech","lastpass","ldapproxy","macos","merakiradius","myworkdrive","netmotion","oam","okta","onelogin","openvpn","openvpnas","owa","paloalto","partner_authapi","partner_websdk","pingfederate","portal","radius","rdgateway","rdp","rdweb","resilient","rest","rras","sailpoint","sailpointweb","samlidp","shibboleth","securex-dashboard","sonicwallsra","sophosutm","splunk","thycotic","tmg","uag","unix","verify","vmwareview","websdk","workday","wordpress")]
        [string]$Type,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminMethods,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAccountInfo,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminIntegrations,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminLogs,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminResources,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminSettings,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowAllAdminWriteResources,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$PhoneCallGreeting,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateCount(0,100)]
        [array]$AllowedGrops,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$AllowNetworks,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Notes,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AllowSelfService,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("None","Simple")]
        [string]$UsernameNormalization,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Key, "Update Integration"))
        {
            [string]$apiPath = "/admin/v1/interations/$($Key)"
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("Type"))
            {
                $parameter["type"] = "$($Type)"
            }
            if($PSBoundParameters.ContainsKey("AllowAllAdminMethods"))
            {
                $parameter["adminapi_admins"] = 1
            }
            if($PSBoundParameters.ContainsKey("AllowAccountInfo"))
            {
                $parameter["adminapi_info"] = 1
            }
            if($PSBoundParameters.ContainsKey("AllowAllAdminIntegrations"))
            {
                $parameter["adminapi_integrations"] = 1
            }
            if($PSBoundParameters.ContainsKey("AllowAllAdminLogs"))
            {
                $parameter["adminapi_read_log"] = 1
            }
            if($PSBoundParameters.ContainsKey("AllowAllAdminResources"))
            {
                $parameter["adminapi_read_resource"] = 1
            }
            if($PSBoundParameters.ContainsKey("AllowAllAdminWriteResources"))
            {
                $parameter["adminapi_write_resource"] = 1
            }
            if($PSBoundParameters.ContainsKey("PhoneCallGreeting"))
            {
                $parameter["greeting"] = "$($PhoneCallGreeting)"
            }
            if($PSBoundParameters.ContainsKey("AllowedGroups"))
            {
                $parameter["groups_allowed"] = @($AllowedGrops)
            }
            if($PSBoundParameters.ContainsKey("AllowNetworks"))
            {
                $parameter["networks_for_api_access"] = @($AllowNetworks)
            }
            if($PSBoundParameters.ContainsKey("Notes"))
            {
                $parameter["notes"] = "$($Notes)"
            }
            if($PSBoundParameters.ContainsKey("AllowSelfService"))
            {
                $parameter["self_service_allowed"] = 1
            }
            if($PSBoundParameters.ContainsKey("UsernameNormalization"))
            {
                $parameter["user_normalization_policy"] = "$($UsernameNormalization)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Update-DuoIntegration.ps1' 222
#Region './Public/Update-DuoLogo.ps1' -1

function Update-DuoLogo {
    <#
    .SYNOPSIS
    Update Logo

    .DESCRIPTION
    Update Logo

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER ImagePath
    Path to the new Logo

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Update-DuoLogo -ApiHostname $ApiHostname -Credential $Credential -ImagePath "C:\Images\NewLogo.png"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateScript({
            if([IO.Path]::GetExtension($_) -ine '.png')
            {
                throw "Invalid file type. The image must be .png"
            }
            return $true
        })]
        [string]$ImagePath,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($GroupId,"Update Logo"))
        {
            [string]$apiPath = "/admin/v1/logo"

            if($PSBoundParameters.ContainsKey("ImagePath"))
            {
                $Logo = ConvertTo-Base64 -Path $ImagePath
                $parameter["logo"] = "$($Logo.B64Encoded)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Update-DuoLogo.ps1' 79
#Region './Public/Update-DuoPhone.ps1' -1

function Update-DuoPhone {
    <#
    .SYNOPSIS
    Update a Phone

    .DESCRIPTION
    Update a Phone

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as Name and SKEY as securestring

    .PARAMETER PhoneNumber
    The new phone number; E.164 format recommended (i.e. "+17345551212").
    If no leading plus sign is provided then it is assumed to be a United States number and an implicit "+1" country code is prepended.

    .PARAMETER Name
    Free-form label for the phone.

    .PARAMETER Extension
    The extension.

    .PARAMETER Type
    The type of phone. One of: "unknown", "mobile", or "landline".

    .PARAMETER Platform
    The phone platform. One of: "unknown", "google android", "apple ios", "windows phone 7", "rim blackberry", "java j2me", "palm webos", "symbian os", "windows mobile", or "generic smartphone".

    "windows phone" is accepted as a synonym for "windows phone 7". This includes devices running Windows Phone 8.

    If a smartphone's exact platform is unknown but it will have Duo Mobile installed, use "generic smartphone" and generate an activation code. When the phone is activated its platform will be automatically detected.

    .PARAMETER AccountId
    Target Account ID. IFTarget account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Update-DuoPhone -ApiHostname $ApiHostname -PhoneNumber '+18888888889' -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateScript({
            if($PSItem -inotmatch '^(\+|\d)(\d+){8,12}$')
            {
                throw "Phone Number must be in E.164 Format. i.e. '+17345551212'. If no leading plus sign is provided then it is assumed to be a United States number and an implicit '+1' country code is prepended"
            }
            return $true
        })]
        [string]$PhoneNumber,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Extension,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("unknown", "mobile", "landline")]
        [string]$Type,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("unknown", "google android", "apple ios", "windows phone 7", "rim blackberry", "java j2me", "palm webos", "symbian os", "windows mobile", "generic smartphone")]
        [string]$Platform = "generic smartphone"

    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Create new Phone"))
        {
            [string]$apiPath = '/admin/v1/phones'
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            if($PSBoundParameters.ContainsKey("PhoneNumber"))
            {
                $parameter["number"] = "$($PhoneNumber)"
            }
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("Extension"))
            {
                $parameter["extension"] = "$($Extension)"
            }
            if($PSBoundParameters.ContainsKey("Type"))
            {
                $parameter["type"] = "$($Type)"
            }
            if($PSBoundParameters.ContainsKey("Platform"))
            {
                $parameter["platform"] = "$($Platform)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Update-DuoPhone.ps1' 125
#Region './Public/Update-DuoPolicy.ps1' -1

function Update-DuoPolicy {
    <#
    .SYNOPSIS
    Update policy with specified parameters.

    .DESCRIPTION
    Update policy with specified parameters.

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER Name
    The name of the policy to create. Policy names do not have to be unique.

    The name parameter may be used instead, but it will be deprecated in a future release.
    Please use policy_name for best results.

    .PARAMETER AffectAllApps
    Values are one of:
    inactive - (default) Use _list keys to specify how policy is applied.
    replace-policy - Apply this policy to all apps, replacing any existing policy.
    apply-policy - Apply this policy to all apps that don’t have a policy applied already.
    unassign-policy - Remove this policy from all apps to which it is applied.
    Warning: Setting this key to any value other than inactive will make changes to all your applications.

    .PARAMETER ApplyList
    An array of apps (specified with app_integration_key) to which to apply this policy.
    If an app in the list has another policy applied, that policy is kept.

    .PARAMETER ReplaceList
    The array of applications (specified with app_integration_key) to which to apply this policy.
    Warning: If the policy is already applied to applications not in the list, it will be removed from those applications.

    .PARAMETER UnassignList
    An array of apps (specified with integration_key) from which to remove this policy.
    If an app in the list has another policy applied, that policy is kept.

    .PARAMETER ApplyGroupPolicyList
    A set of groups (specified with group_id_list) to which to apply this policy.

    .PARAMETER GroupPolicyApplyOrder
    Values are one of:
    existing - (default) If the group policy being applied already exists for this application, keep its place in the stack. If it doesn’t exist, add it to the top of the stack.
    top - Place this policy on the top of the group policy stack.
    bottom - Place this policy on the bottom of the group policy stack.

    .PARAMETER ReplaceGroupPolicyList
    A set of groups (specified with group_id_list) to which to apply this policy.
    If you specify a blank array ([]) as a value, all groups applied to this policy in this app will be replaced with nothing (that is, unassigned).

    .PARAMETER UnassignGroupPolicyList
    A set of groups (specified with group_id_list) from which to remove this policy.

    .PARAMETER AnonymousAccessBehavior
    Defines what happens when a user on an anonymous network attempts to access resources. One of no-action (default), require-mfa, or deny.

    .PARAMETER AllowedAuthList
    Comma-separated list of allowed authentication methods. The list defaults to: duo-push, hardware-token, webauthn-platform, webauthn-roaming, and sms.
    If Duo Passwordless is turned on for your account, there are three additional authentication methods available: duo-push-pwl, webauthn-platform-pwl, and webauthn-roaming-pwl.

    .PARAMETER AutoRetrySms
    Is true if a new SMS passcode will be sent up to 3 times when delivery fails. Otherwise false (default).
    Any retries will use additional telephony credits

    .PARAMETER BlockedAuthList
    Comma-separated list of blocked authentication methods.
    The list defaults to: duo-passcode and phonecall

    .PARAMETER RequireVerifiedPush
    Is true (default) if the user logging in must verify the push by entering the number provided on their authentication device.
    Otherwise false. Applies if duo-push is in the allowed_auth_list.

    .PARAMETER VerifiedPushDigits
    The number of digits a verified push requires the user to enter. An integer between 3 and 6, inclusive. Defaults to 3

    .PARAMETER UserAuthBehavior
    Defines the behavior when a user authenticates. One of:
    enforce (default): Requires 2FA or enrollment when applicable, unless another policy supersedes it.
    bypass: Skips 2FA and enrollment, unless another policy supersedes it.
    deny: Denies authentication to all users.
    Affects all users when enabled.

    .PARAMETER NoMfaRequiredIpList
    Comma-separated list of public IP addresses for which 2FA is not required.
    IP address lists can contain individual IPs, IP ranges and IP ranges in CIDR notation.
    Example: ["192.0.2.8", "198.51.100.0-198.51.100.20", "203.0.113.0/24"]

    .PARAMETER RequireEnrollment
    Is true (default) if users logging in from these IP addresses must enroll in Duo.
    Otherwise false. At least one value must be in the ip_list to change this value.

    .PARAMETER MfaRequiredIpList
    Comma-separated list of public IP addresses for which MFA is required.
    IP address lists can contain individual IPs, IP ranges and IP ranges in CIDR notation.
    Example: ["192.0.2.8", "198.51.100.0-198.51.100.20", "203.0.113.0/24"]

    .PARAMETER DenyOtherAccess
    Is true if users must log in from IP addresses listed in one of the ip_list keys above.
    Otherwise false (default). At least one IP address must be in either of the ip_list keys above to change this value.
    This key is available in the Premier and Advantage editions.

    .PARAMETER AllowedBrowsersList
    Comma-separated list of allowed browsers. Default behavior permits all browsers.

    .PARAMETER BlockedBrowsersList
    Comma-separated list of blocked browsers. Default: none.

    .PARAMETER OutOfDateBehavior
    Value is one of warn-only, warn-and-block, or no-remediation (default).
    This affects all browsers in the allowed_browsers_list.

    .PARAMETER BrowserMaxOutOfDateDays
    The number of days that a browser may be out of date before access to it is blocked (out_of_date_behavior must be warn-and-block for the browser to be blocked).
    Value is one of 0, 14, 30 (default), 60, 90, 180, or 365.
    Other values are invalid.

    .PARAMETER RequiresDha
    Comma-separated list of operating systems that require the Duo Device Health App (one or more of macos or windows).
    Listing an operating system here is the equivalent of setting “Enforcing” for that OS when editing a policy in the Admin Panel

    .PARAMETER PromptToInstallDha
    Comma-separated list of operating systems that will prompt to install the Duo Device Health App during enrollment (one or more of macos or windows).

    .PARAMETER EnforceFirewall
    Comma-separated list of operating systems that will require a firewall to be active (one or more of macos or windows).
    This key is available in the Premier and Advantage editions.

    .PARAMETER EnforceEncryption
    Comma-separated list of operating systems that will require the hard drive to be encrypted (one or more of macos or windows).
    This key is available in the Premier and Advantage editions.

    .PARAMETER EnforceSystemPassword
    Comma-separated list of operating systems that will require a system password to be set (one or more of macos or windows).
    This key is available in the Premier and Advantage editions.

    .PARAMETER MacOsRemediationNote
    A text note (max 700 characters) with remediation instructions when an end user is blocked.
    This key is available in the Premier edition.

    .PARAMETER MacOsEndpointSecurityList
    Comma-separated list of Duo-supported endpoint security agents that are allowed.
    For agents in this list, the app will block access unless one of those agents is running.
    A complete list of macOS security agents is available in a drop-down when editing the policy in the Admin Panel.
    This key is available in the Premier edition.

    .PARAMETER WindowsEndpointSecurityList
    omma-separated list of Duo-supported endpoint security agents that are allowed.
    For agents in this list, the app will block access unless one of those agents is running.
    A complete list of Windows security agents is available in a drop-down when editing the policy in the Admin Panel.
    This key is available in the Premier edition.

    .PARAMETER WindowsRemediationNote
    A text note (max 700 characters) with remediation instructions when an end user is blocked.
    This key is available in the Premier edition.

    .PARAMETER RequireDuoAppUpdates
    Is true (default) if the Duo Mobile app must have up-to-date security patches. Otherwise false.

    .PARAMETER RequiresFullDiskEncryption
    Is true if the device used for authentication requires full-disk encryption. Otherwise false (default).

    .PARAMETER RequiresMobileDeviceBiometrics
    Is true if the mobile device used to authenticate requires Apple Touch ID, Face ID, or Android Fingerprint as additional verification when approving Duo Push login requests. Otherwise false (default).

    .PARAMETER NewUserBehavior
    Controls what happens after an unenrolled user passes primary authentication. One of:
    enroll (default): Require the user to enroll whenever possible.
    no-mfa: MFA is not required for unknown users; unenrolled users must enroll.
    deny: Denies authentication to unenrolled users.


    .PARAMETER AllowUnrestrictedOsList
    Comma-separated list of operating systems that are allowed with no constraints or warnings.
    AllowUnrestrictedOsList and BlockOsList must not contain the same values.

    .PARAMETER BlockOsList
    Comma-separated list of operating systems that are not allowed.
    AllowUnrestrictedOsList and BlockOsList must not contain the same values.
    Blocked Android or iOS versions will not be able to authenticate using Duo Push or Duo Mobile passcodes.

    .PARAMETER OperatingSystemToRestrict
    Operating systems that can be further restricted: android, ios, macos, and windows.

    .PARAMETER OsWarnPolicy
    Indicates when the user should be warned that their OS is out of date. Value is one of:
    no-remediation (default): No version checking; equivalent to “Never” when editing the policy in the UI.
    end-of-life: OS vendor no longer releases security updates.
    not-up-to-date: OS is not at the most recent patch release version.
    less-than-latest: OS is not at the most recently released version.
    less-than-version: OS is older than the version specified in warn_version.


    .PARAMETER OsWarnVersion
    The specific OS version (from the list in the edit policy UI) subject to the out-of-date warning.
    Applicable only if warn_policy is less-than-version.

    .PARAMETER OsWarnRemediationDays
    Number of days that the user will be warned.
    Value is one of 0, 14, 30 (default), 60, 90, 180, or 365.

    .PARAMETER OsBlockPolicy
    Indicates when the user will be blocked from access.
    Values are the same as warn_policy.

    .PARAMETER OsBlockVersion
    The specific OS version (from the list in the edit policy UI) that is being blocked.
    Values are the same as warn_version.
    Applicable only if block_policy is less-than-version.

    .PARAMETER OsBlockRemediationDays
    Number of days before the user will be blocked.
    Values are the same as warn_remediation_days.

    .PARAMETER FlashPlugin
    Specify how Flash plugins are treated. Value is one of allow-all or block-all (default).

    .PARAMETER JavaPlugin
    Specify how Java plugins are treated. Value is one of:
    allow-all: No restrictions.
    warn-only (default): Warn if plugin is out of date.
    warn-and-block: warn if out of date; block after java_max_ood_days.
    block-all: Blocked; no access.


    .PARAMETER JavaMaxOutOfDateDays
    The number of days that Java plugins may be out of date before access is blocked (java must be warn-and-block for the plugin to be blocked).
    Value is one of 0, 14, 30 (default), 60, 90, 180, or 365.
    Other values are invalid.

    .PARAMETER BrowserAppsEnabled
    Is true if devices are remembered for browser-based apps. Otherwise false (default).

    .PARAMETER BrowserAppsRememberMethod
    One of user-based (default) or risk-based. risk-based only available in the Premier and Advantage editions.

    .PARAMETER BrowserAppsUserBasedConfirmPerApp
    s true if the user must confirm for each browser-based app separately. Otherwise false (default).

    .PARAMETER BrowserAppsUserBasedMaxTimeUnits
    One of days or hours (default).

    .PARAMETER BrowserAppsUserBasedMaxTimeValue
    If max_time_units is set to:
    days: an integer 1 to 365, inclusive.
    hours: an integer 1 to 8760, inclusive.
    Defaults to 12.

    .PARAMETER BrowserAppsRiskBasedMaxTimeUnits
    One of days or hours (default).

    .PARAMETER BrowserAppsRiskBasedMaxTimeValue
    If max_time_units is set to:
    days: an integer 1 to 365, inclusive.
    hours: an integer 1 to 8760, inclusive.
    Defaults to 30.

    .PARAMETER WindowsLogonEnabled
    Is true if devices are remembered for Windows Logon. Otherwise false (default).
    2FA will be enforced after users sign out, reboot, or change networks.

    .PARAMETER WindowsLogonMaxTimeUnits
    One of days (default) or hours.

    .PARAMETER WindowsLogonMaxTimeValue
    If max_time_units is set to:
    days: an integer 1 to 365, inclusive.
    hours: an integer 1 to 8760, inclusive.
    Defaults to 30.

    .PARAMETER LimitToRiskBasedAuthMethods
    s true if the user is limited to risk-based authentication methods when Duo detects a higher-risk authentication. Otherwise false (default).

    .PARAMETER RiskBasedVerifiedPushDigits
    The number of digits a verified push requires the user logging in to enter. An integer between 3 and 6, inclusive. Defaults to 6.

    .PARAMETER RequiresScreenLock
    Is true (default) if the device must have a screen lock to be allowed for authentication. Otherwise false. Applies to iOS (8 and up) and Android.

    .PARAMETER BlockTamperedDevices
    Is true (default) if iOS or Android devices that are rooted or otherwise tampered with are not allowed for authentication. Otherwise false.

    .PARAMETER TrustedEndpointChecking
    Value is one of allow-all (default), require-trusted, or not-configured. Value will be not-configured if Trusted Endpoints management systems have not been configured.
    Trusted endpoints will still be checked for reporting purposes if allow-all is set, but untrusted endpoints will be allowed.

    .PARAMETER CiscoSecureEndpointCanBlock
    Is true if Cisco Secure Endpoint is allowed to block compromised endpoints. Otherwise false (default).

    .PARAMETER TrustedEndpointCheckingMobile
    Allowed values and default are the same as trusted_endpoint_checking.
    Duo recommends not setting this value separately from trusted_endpoint_checking.
    Since the user-agent string is self-reported by the browser, it's possible to manipulate it from the client side to change the value reported to Duo, with the potential effect of bypassing a policy intended to block access.

    .PARAMETER RequireMfaCountriesList
    List of one or more country codes. If the user’s location matches one of the codes, that user is required to use MFA to authenticate.

    .PARAMETER DenyAccessCountriesList
    List of one or more country codes. If the user’s location matches one of the codes, that user is denied access.

    .PARAMETER AllowAccessNoMfaCountriesList
    List of one or more country codes. If the user’s location matches one of the codes, that user is allowed access without 2FA.

    .PARAMETER IgnoreLocationCountriesList
    List of one or more country codes. If the user’s location matches one of the codes, no action is taken.

    .PARAMETER DefaultAction
    Indicates behavior for country codes that aren’t in any list. Values are one of:
    deny-access: User is denied access.
    ignore-location (default): No action is taken.
    require-mfa: User must use MFA to authenticate.
    allow-access-no-2fa: User is allowed access without 2FA.

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .EXAMPLE
    PS>Update-DuoPolicy -Name "MyNewPolicy" -ApiHostname $ApiHostname -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High", DefaultParameterSetName="A")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$PolicyKey,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Name,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("inactive","replace-policy","apply-policy","unassign-policy")]
        [string]$AffectAllApps,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$ApplyList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$ReplaceList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$UnassignList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$ApplyGroupPolicyList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("existing","top","bottom")]
        [string]$GroupPolicyApplyOrder,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$ReplaceGroupPolicyList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$UnassignGroupPolicyList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("no-action","require-mfa","deny")]
        [string]$AnonymousAccessBehavior,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$AllowedAuthList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$AutoRetrySms,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$BlockedAuthList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequireVerifiedPush,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(3,6)]
        [int]$VerifiedPushDigits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("enforce","bypass","deny")]
        [string]$UserAuthBehavior,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$NoMfaRequiredIpList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequireEnrollment,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$MfaRequiredIpList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$DenyOtherAccess,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$AllowedBrowsersList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$BlockedBrowsersList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("warn-only","warn-and-block","no-remediation")]
        [string]$OutOfDateBehavior,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet(0,14,30,60,90,180,365)]
        [int]$BrowserMaxOutOfDateDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$RequiresDha,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$PromptToInstallDha,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$EnforceFirewall,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$EnforceEncryption,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$EnforceSystemPassword,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$MacOsEndpointSecurityList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateLength(0,700)]
        [string]$MacOsRemediationNote,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$WindowsEndpointSecurityList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateLength(0,700)]
        [string]$WindowsRemediationNote,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequireDuoAppUpdates,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequiresFullDiskEncryption,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequiresMobileDeviceBiometrics,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("enroll","no-mfa","deny")]
        [string]$NewUserBehavior,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateScript({
            foreach($value in $_)
            {
                if($value -inotin @("android","blackberry","chromeos","ios","linux","macos","windows","windowsphone","unknownos"))
                {
                    throw 'Invalid Entry ' + $value + '. Allowed Values: "android","blackberry","chromeos","ios","linux","macos","windows","windowsphone", and "unknownos"'
                }
            }
            return $true
        })]
        [array]$AllowUnrestrictedOsList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateScript({
            foreach($value in $_)
            {
                if($value -inotin @("android","blackberry","chromeos","ios","linux","macos","windows","windowsphone","unknownos"))
                {
                    throw 'Invalid Entry ' + $value + '. Allowed Values: "android","blackberry","chromeos","ios","linux","macos","windows","windowsphone", and "unknownos"'
                }
            }
            return $true
        })]
        [array]$BlockOsList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("android", "ios", "macos", "windows")]
        [string]$OperatingSystemToRestrict,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("no-remediation","end-of-life","not-up-to-date","less-than-latest","less-than-version")]
        [string]$OsWarnPolicy,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$OsWarnVersion,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet(0,14,30,60,90,180,365)]
        [string]$OsWarnRemediationDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("no-remediation","end-of-life","not-up-to-date","less-than-latest","less-than-version")]
        [string]$OsBlockPolicy,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$OsBlockVersion,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet(0,14,30,60,90,180,365)]
        [string]$OsBlockRemediationDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("allow-all","block-all")]
        [string]$FlashPlugin,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("allow-all","warn-only","warn-and-block","block-all")]
        [string]$JavaPlugin,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet(0,14,30,60,90,180,365)]
        [string]$JavaMaxOutOfDateDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$BrowserAppsEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("user-based","risk-based")]
        [string]$BrowserAppsRememberMethod,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$BrowserAppsUserBasedConfirmPerApp,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("days","hours")]
        [string]$BrowserAppsUserBasedMaxTimeUnits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$BrowserAppsUserBasedMaxTimeValue,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("days","hours")]
        [string]$BrowserAppsRiskBasedMaxTimeUnits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$BrowserAppsRiskBasedMaxTimeValue,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$WindowsLogonEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("days","hours")]
        [string]$WindowsLogonMaxTimeUnits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$WindowsLogonMaxTimeValue,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$LimitToRiskBasedAuthMethods,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(3,6)]
        [int]$RiskBasedVerifiedPushDigits,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$RequiresScreenLock,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$BlockTamperedDevices,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("allow-all","require-trusted","not-configured")]
        [string]$TrustedEndpointChecking,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$CiscoSecureEndpointCanBlock,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("allow-all","require-trusted","not-configured")]
        [string]$TrustedEndpointCheckingMobile,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$RequireMfaCountriesList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$DenyAccessCountriesList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$AllowAccessNoMfaCountriesList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [array]$IgnoreLocationCountriesList,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("deny-access", "ignore-location","require-mfa","allow-access-no-2fa")]
        [string]$DefaultAction,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId

    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}
    }
    Process{
        if($PSCmdlet.ShouldProcess($Name, "Update policy"))
        {
            [string]$apiPath = "/admin/v2/policies/$($PolicyKey)"
            if($PSBoundParameters.ContainsKey("Name"))
            {
                $parameter["policy_name"] = "$($Name)"
            }
            if($PSBoundParameters.ContainsKey("AffectAllApps"))
            {
                $parameter["apply_to_apps"] = @{"affect_all_apps" = $($AffectAllApps)}
            }
            if($PSBoundParameters.ContainsKey("ApplyList"))
            {
                $parameter["apply_to_apps"] = @{"apply_list" = $($ApplyList)}
            }
            if($PSBoundParameters.ContainsKey("ReplaceList"))
            {
                $parameter["apply_to_apps"] = @{"replace_list" = $($ReplaceList)}
            }
            if($PSBoundParameters.ContainsKey("UnassignList"))
            {
                $parameter["apply_to_apps"] = @{"unassign_list" = $($UnassignList)}
            }
            if($PSBoundParameters.ContainsKey("ApplyGroupPolicyList"))
            {
                $parameter["apply_to_groups_in_apps"] = @{"apply_group_policy_list" = $($ApplyGroupPolicyList)}
            }
            if($PSBoundParameters.ContainsKey("GroupPolicyApplyOrder"))
            {
                $parameter["apply_to_groups_in_apps"] = @{"group_policy_apply_order" = $($GroupPolicyApplyOrder)}
            }
            if($PSBoundParameters.ContainsKey("ReplaceGroupPolicyList"))
            {
                $parameter["apply_to_groups_in_apps"] = @{"replace_group_policy_list" = $($ReplaceGroupPolicyList)}
            }
            if($PSBoundParameters.ContainsKey("UnassignGroupPolicyList"))
            {
                $parameter["apply_to_groups_in_apps"] = @{"unassign_group_policy_list" = $($UnassignGroupPolicyList)}
            }
            if($PSBoundParameters.ContainsKey("AnonymousAccessBehavior"))
            {
                $parameter["sections"] = @{
                    "anonymous_networks" = @{
                        "anonymous_access_behavior" = $($AnonymousAccessBehavior)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("AllowedAuthList"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "allowed_auth_list" = @($($AllowedAuthList))
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("AutoRetrySms"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "auto-retry-sms" = $($AutoRetrySms)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BlockedAuthList"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "blocked_auth_list" = $($BlockedAuthList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequireVerifiedPush"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "require_verified_push" = $($RequireVerifiedPush)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequireVerifiedPush"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "verified_push_digits" = $($RequireVerifiedPush)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("VerifiedPushDigits"))
            {
                $parameter["sections"] = @{
                    "authentication_methods" = @{
                        "verified_push_digits" = $($VerifiedPushDigits)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("UserAuthBehavior"))
            {
                $parameter["sections"] = @{
                    "authentication_policy" = @{
                        "user_auth_behavior" = $($UserAuthBehavior)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("NoMfaRequiredIpList"))
            {
                $parameter["sections"] = @{
                    "authorized_networks" = @{
                        "no_2fa_required" = @{
                            "ip_list" = $($NoMfaRequiredIpList)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequireEnrollment"))
            {
                $parameter["sections"] = @{
                    "authorized_networks" = @{
                        "no_2fa_required" = @{
                            "require_enrollment" = $($RequireEnrollment)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("MfaRequiredIpList"))
            {
                $parameter["sections"] = @{
                    "authorized_networks" = @{
                        "mfa_required" = @{
                            "ip_list" = $($MfaRequiredIpList)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("DenyOtherAccess"))
            {
                $parameter["sections"] = @{
                    "authorized_networks" = @{
                        "deny_other_access" = $($DenyOtherAccess)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("AllowedBrowsersList"))
            {
                $parameter["sections"] = @{
                    "browsers" = @{
                        "allowed_browsers_list" = $($AllowedBrowsersList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BlockedBrowsersList"))
            {
                $parameter["sections"] = @{
                    "browsers" = @{
                        "blocked_browsers_list" = $($BlockedBrowsersList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("OutOfDateBehavior"))
            {
                $parameter["sections"] = @{
                    "browsers" = @{
                        "out_of_date_behavior" = $($OutOfDateBehavior)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserMaxOutOfDateDays"))
            {
                $parameter["sections"] = @{
                    "browsers" = @{
                        "browser_max_ood_days" = $($BrowserMaxOutOfDateDays)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequiresDha"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "requires_DHA" = $($RequiresDha)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("PromptToInstallDha"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "prompt_to_install" = $($PromptToInstallDha)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("EnforceFirewall"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "enforce_firewall" = $($EnforceFirewall)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("EnforceEncryption"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "enforce_encryption" = $($EnforceEncryption)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("EnforceSystemPassword"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "enforce_system_password" = $($EnforceSystemPassword)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("MacOsEndpointSecurityList"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "macos_endpoint_security_list" = $($MacOsEndpointSecurityList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("MacOsRemediationNote"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "macos_remediation_note" = $($MacOsRemediationNote)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("WindowsEndpointSecurityList"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "windows_endpoint_security_list" = $($WindowsEndpointSecurityList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("WindowsRemediationNote"))
            {
                $parameter["sections"] = @{
                    "device_health_app" = @{
                        "windows_remediation_note" = $($WindowsRemediationNote)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequireDuoAppUpdates"))
            {
                $parameter["sections"] = @{
                    "duo_mobile_app" = @{
                        "require_updates" = $($RequireDuoAppUpdates)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequiresFullDiskEncryption"))
            {
                $parameter["sections"] = @{
                    "full_disk_encryption" = @{
                        "require_encryption" = $($RequiresFullDiskEncryption)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequiresMobileDeviceBiometrics"))
            {
                $parameter["sections"] = @{
                    "mobile_device_biometrics" = @{
                        "require_biometrics" = $($RequiresMobileDeviceBiometrics)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("NewUserBehavior"))
            {
                $parameter["sections"] = @{
                    "new_user" = @{
                        "new_user_behavior" = $($NewUserBehavior)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("AllowUnrestrictedOsList"))
            {
                $parameter["sections"] = @{
                    "operating_systems" = @{
                        "allow_unrestricted_os_list" = $($AllowUnrestrictedOsList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BlockOsList"))
            {
                $parameter["sections"] = @{
                    "operating_systems" = @{
                        "block_os_list" = $($BlockOsList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("OperatingSystemToRestrict"))
            {
                [hashtable]$OsRestrictions = @{}
                if($PSBoundParameters.ContainsKey("OsWarnPolicy"))
                {
                    $OsRestrictions["warn_policy"] = $OsWarnPolicy
                }
                if($PSBoundParameters.ContainsKey("OsWarnVersion"))
                {
                    $OsRestrictions["warn_version"] = $OsWarnVersion
                }
                if($PSBoundParameters.ContainsKey("OsWarnRemediationDays"))
                {
                    $OsRestrictions["warn_remediation_days"] = $OsWarnRemediationDays
                }
                if($PSBoundParameters.ContainsKey("OsBlockPolicy"))
                {
                    $OsRestrictions["block_policy"] = $OsBlockPolicy
                }
                if($PSBoundParameters.ContainsKey("OsBlockVersion"))
                {
                    $OsRestrictions["block_version"] = $OsBlockVersion
                }
                if($PSBoundParameters.ContainsKey("OsBlockRemediationDays"))
                {
                    $OsRestrictions["block_remediation_days"] = $OsBlockRemediationDays
                }
                $parameter["sections"] = @{
                    "operating_systems" = @{
                        $OperatingSystemToRestrict = @{
                            "os_restrictions" = $OsRestrictions
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("FlashPlugin"))
            {
                $parameter["sections"] = @{
                    "plugins" = @{
                        "flash" = $($FlashPlugin)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("JavaPlugin"))
            {
                $parameter["sections"] = @{
                    "plugins" = @{
                        "java" = $($JavaPlugin)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("JavaMaxOutOfDateDays"))
            {
                $parameter["sections"] = @{
                    "plugins" = @{
                        "java_max_ood_days" = $($JavaMaxOutOfDateDays)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsEnabled"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "enabled" = $($BrowserAppsEnabled)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsRememberMethod"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "remember_method" = $($BrowserAppsRememberMethod)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsUserBasedConfirmPerApp"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "user_based" = @{
                                "confirm_per_app" = $($BrowserAppsUserBasedConfirmPerApp)
                            }
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsUserBasedMaxTimeUnits"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "user_based" = @{
                                "max_time_units" = $($BrowserAppsUserBasedMaxTimeUnits)
                            }
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsUserBasedMaxTimeValue"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "user_based" = @{
                                "max_time_value" = $($BrowserAppsUserBasedMaxTimeValue)
                            }
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsRiskBasedMaxTimeUnits"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "risk_based" = @{
                                "max_time_units" = $($BrowserAppsRiskBasedMaxTimeUnits)
                            }
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BrowserAppsRiskBasedMaxTimeValue"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "browser_apps" = @{
                            "risk_based" = @{
                                "max_time_value" = $($BrowserAppsRiskBasedMaxTimeValue)
                            }
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("WindowsLogonEnabled"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "windows_logon" = @{
                            "enabled" = $($WindowsLogonEnabled)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("WindowsLogonMaxTimeUnits"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "windows_logon" = @{
                            "max_time_units" = $($WindowsLogonMaxTimeUnits)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("WindowsLogonMaxTimeValue"))
            {
                $parameter["sections"] = @{
                    "remembered_devices" = @{
                        "windows_logon" = @{
                            "max_time_value" = $($WindowsLogonMaxTimeValue)
                        }
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("LimitToRiskBasedAuthMethods"))
            {
                $parameter["sections"] = @{
                    "risk_based_factor_selection" = @{
                        "limit_to_risk_based_auth_methods" = $($LimitToRiskBasedAuthMethods)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RiskBasedVerifiedPushDigits"))
            {
                $parameter["sections"] = @{
                    "risk_based_factor_selection" = @{
                        "risk_based_verified_push_digits" = $($RiskBasedVerifiedPushDigits)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequiresScreenLock"))
            {
                $parameter["sections"] = @{
                    "screen_lock" = @{
                        "require_screen_lock" = $($RequiresScreenLock)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("BlockTamperedDevices"))
            {
                $parameter["sections"] = @{
                    "tampered_devices" = @{
                        "block_tampered_devices" = $($BlockTamperedDevices)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("TrustedEndpointChecking"))
            {
                $parameter["sections"] = @{
                    "trusted_endpoints" = @{
                        "trusted_endpoint_checking" = $($TrustedEndpointChecking)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("CiscoSecureEndpointCanBlock"))
            {
                $parameter["sections"] = @{
                    "trusted_endpoints" = @{
                        "cisco_secure_endpoint_can_block" = $($CiscoSecureEndpointCanBlock)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("TrustedEndpointCheckingMobile"))
            {
                $parameter["sections"] = @{
                    "trusted_endpoints" = @{
                        "trusted_endpoint_checking_mobile" = $($TrustedEndpointCheckingMobile)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("RequireMfaCountriesList"))
            {
                $parameter["sections"] = @{
                    "user_location" = @{
                        "require_mfa_countries_list" = $($RequireMfaCountriesList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("DenyAccessCountriesList"))
            {
                $parameter["sections"] = @{
                    "user_location" = @{
                        "deny_access_countries_list" = $($DenyAccessCountriesList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("AllowAccessNoMfaCountriesList"))
            {
                $parameter["sections"] = @{
                    "user_location" = @{
                        "allow_access_no_2fa_countries_list" = $($AllowAccessNoMfaCountriesList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("IgnoreLocationCountriesList"))
            {
                $parameter["sections"] = @{
                    "user_location" = @{
                        "ignore_location_countries_list" = $($IgnoreLocationCountriesList)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("DefaultAction"))
            {
                $parameter["sections"] = @{
                    "user_location" = @{
                        "default_action" = $($DefaultAction)
                    }
                }
            }
            if($PSBoundParameters.ContainsKey("Description"))
            {
                $parameter["desc"] = "$($Description)"
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Update-DuoPolicy.ps1' 1180
#Region './Public/Update-DuoSetting.ps1' -1

function Update-DuoSetting {
    <#
    .SYNOPSIS
    Change global Duo settings

    .DESCRIPTION
    Change global Duo settings

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER CallerId
    Automated calls will appear to come from this number. This does not apply to text messages.
    Customizing this number may cause telephony providers to flag your number as fraudulent and result in failed user authentications.

    .PARAMETER EmailActivityNotificationEnabled
    If true, users will receive an email notification when an authentication device is added or removed.
    If set to false, no email notifications are sent in these situations. Default value is false

    .PARAMETER FraudEmail
    The email address to be notified when a user reports a fraudulent authentication attempt or is locked out due to failed authentication attempts, or empty for all administrators will be notified.
    If fraud_email is set to a specific email address and fraud_email_enabled is set to false, the specific email address value is cleared.

    .PARAMETER FraudEmailEnabled
    Set to true to enable fraudulent authentication notification emails.
    False disables the fraud email functionality.
    If fraud_email is set to a specific email address and fraud_email_enabled is set to false, the specific email address value is cleared.

    .PARAMETER GlobalSspPolicyEnforced
    If true, a policy set by an administrator is enforced for users trying to access the self-service portal.
    If set to false, the policy to access the self-service portal will be determined by the destination application policy. Default value is true.

    .PARAMETER HelpDeskBypass
    Grants permission for administrators with the Help Desk role to generate bypass codes for users.
    The default value allow permits unrestricted generation of bypass codes,
    limit plus a value for helpdesk_bypass_expiration allows Help Desk admins to generate bypass codes with a preset expirtation,
    and deny prevents Help Desk admins from generating any bypass codes.

    .PARAMETER HelpDeskExpirationMin
    Integer specifying a default expiration for bypass codes generated by Help Desk admins, in minutes.
    If not set, Help Desk admins may change bypass code expiration from the default 60 minutes after creation if helpdesk_bypass is set to allow.
    If specifying a value, also set helpdesk_bypass to limit.

    .PARAMETER HelpDeskCanSendEnrollEmail
    Permits Help Desk administrators to send or resend enrollment emails to users.
    Set to true to allow sending of enrollment emails. Default value is false.

    .PARAMETER InactiveUserExpirationDays
    Users will be automatically deleted if they are inactive (no successful logins) for this number of days.
    Minimum: 30 Maximum: 365

    .PARAMETER KeyPressConfirm
    The key for users to press to authenticate, or empty if any key should be pressed to authenticate. If this is empty, keypress_fraud must be as well.

    .PARAMETER KeyPressFraud
    The key for users to report fraud, or empty if any key should be pressed to authenticate. If this is empty, keypress_confirm must be as well.

    .PARAMETER Language
    Sets the language used in the browser-based user authentication prompt. One of: "EN", "DE", "FR". Default: "EN"

    .PARAMETER LockoutExpireDurationMin
    If non-zero, the time in minutes until a locked-out user's status reverts to "Active".
    If 0, a user remains locked out until their status is manually changed (By an admin or API call). Minimum: 5 Maximum: 30000

    .PARAMETER LockoutThreshold
    The number of consecutive failed authentication attempts before the user's status is set to "Locked Out" and the user is denied access. Default is 10 attempts. Minimum: 1 Maximum: 9999

    .PARAMETER LogRetentionDays
    When set, log entries older than the specified number of days are purged. Logs retained indefinitely if null.
    Note that the log retention setting does not change the 180 day limitation for viewing and retrieving log information in the Duo Admin Panel, exported reports, or via this API.
    Default: null (no retention limit). Minimum: 1 day. Maximum: 365 days.

    .PARAMETER MinPasswordLength
    he minimum number of characters that an administrator's Duo Admin Panel password must contain.
    This is only enforced on password creation and reset; existing passwords will not be invalidated. Default: 12. Minimum: 12 Maximum: 100

    .PARAMETER PasswordRequiresLowerAlpha
    If true, administrator passwords will be required to contain a lower case alphabetic character. If false, administrator passwords will not be required to contain a lower case alphabetic character.
    This is only enforced on password creation and reset; existing passwords will not be invalidated.
    Default: false.

    .PARAMETER PasswordRequiresSpecial
    If true, administrator passwords will be required to contain a special (non-alphanumeric) character. If false, administrator passwords will not be required to contain a special (non-alphanumeric) character.
    This is only enforced on password creation and reset; existing passwords will not be invalidated. Default: false

    .PARAMETER PasswordRequiresUpperAlpha
    If true, administrator passwords will be required to contain an upper case alphabetic character. If false, administrator passwords will not be required to contain an upper case alphabetic character.
    This is only enforced on password creation and reset; existing passwords will not be invalidated. Default: false.

    .PARAMETER PasswordRequiresNumeric
    If true, administrator passwords will be required to contain a numeric character. If false, administrator passwords will not be required to contain a numeric character.
    This is only enforced on password creation and reset; existing passwords will not be invalidated. Default: false.

    .PARAMETER PushActivityNotificationEnabled
    If true, users will receive a Duo Mobile notification when an authentication device is added or removed.
    If set to false, no email notifications are sent in these situations. Default value is false

    .PARAMETER SmsBatch
    The number of passcodes to send at one time, up to 10.

    .PARAMETER SmsExpirationMin
    The time in minutes to expire and invalidate SMS passcodes, or empty if they should not expire.

    .PARAMETER SmsMessage
    escription sent with every batch of SMS passcodes.

    .PARAMETER SmsRefresh
    If True, a new set of SMS passcodes will automatically be sent after the last one is used. If false, a new set will not be sent.

    .PARAMETER TelephonyWarningMin
    Configure a alert to be sent when the account has fewer than this many telephony credits remaining

    .PARAMETER Timezone
    This is the timezone used when displaying timestamps in the Duo Admin Panel. Timezones must be entries in the IANA Time Zone Database, for example, "US/Eastern", "Australia/Darwin", "GMT".

    .PARAMETER UserManagersCanPutUsersInBypass
    Permits User Manager administrators to apply "Bypass" status to users.
    Set to false to prevent User Managers from applying "Bypass" status. Default value is true.

    .PARAMETER UserTelephonyCostMax
    The maximum number of telephony credits a user may consume in a single authentication event.
    This excludes Duo administrators authenticating to the Duo administration panel. If you know the countries from which your users expect to authenticate with phone callback we recommend adjusting this down from the default to match the most expensive expected country to help avoid misuse, using the values from the Telephony Credits documentation.
    Default: 20.

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Update-DuoSetting -ApiHostname $ApiHostname -Credential $Credential -MinPasswordLength 32
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$CallerId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$EmailActivityNotificationEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$FraudEmail,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$FraudEmailEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$GlobalSspPolicyEnforced,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("allow","limit","deny")]
        [string]$HelpDeskBypass,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$HelpDeskExpirationMin,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$HelpDeskCanSendEnrollEmail,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$InactiveUserExpirationDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$KeyPressConfirm,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$KeyPressFraud,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("EN","DE","FR")]
        [string]$Language,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(5,30000)]
        [int]$LockoutExpireDurationMin,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(1,9999)]
        [int]$LockoutThreshold,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(1,365)]
        [int]$LogRetentionDays,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(12,100)]
        [int]$MinPasswordLength,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$PasswordRequiresLowerAlpha,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$PasswordRequiresNumeric,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$PasswordRequiresSpecial,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$PasswordRequiresUpperAlpha,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$PushActivityNotificationEnabled,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateRange(0,10)]
        [int]$SmsBatch,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$SmsExpirationMin,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$SmsMessage,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$SmsRefresh,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$TelephonyWarningMin,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("Africa/Abidjan","Africa/Algiers","Africa/Bissau","Africa/Cairo","Africa/Casablanca","Africa/Ceuta","Africa/El_Aaiun","Africa/Johannesburg","Africa/Juba","Africa/Khartoum","Africa/Lagos","Africa/Maputo","Africa/Monrovia","Africa/Nairobi","Africa/Ndjamena","Africa/Sao_Tome","Africa/Tripoli","Africa/Tunis","Africa/Windhoek","America/Adak","America/Anchorage","America/Araguaina","America/Argentina","America/Argentina","America/Argentina","America/Argentina","America/Argentina","America/Argentina","America/Argentina","America/Argentina","America/Argentina","America/Argentina","America/Argentina","America/Argentina","America/Asuncion","America/Bahia","America/Bahia_Banderas","America/Barbados","America/Belem","America/Belize","America/Boa_Vista","America/Bogota","America/Boise","America/Cambridge_Bay","America/Campo_Grande","America/Cancun","America/Caracas","America/Cayenne","America/Chicago","America/Chihuahua","America/Ciudad_Juarez","America/Costa_Rica","America/Cuiaba","America/Danmarkshavn","America/Dawson","America/Dawson_Creek","America/Denver","America/Detroit","America/Edmonton","America/Eirunepe","America/El_Salvador","America/Fort_Nelson","America/Fortaleza","America/Glace_Bay","America/Goose_Bay","America/Grand_Turk","America/Guatemala","America/Guayaquil","America/Guyana","America/Halifax","America/Havana","America/Hermosillo","America/Indiana","America/Indiana","America/Indiana","America/Indiana","America/Indiana","America/Indiana","America/Indiana","America/Indiana","America/Inuvik","America/Iqaluit","America/Jamaica","America/Juneau","America/Kentucky","America/Kentucky","America/La_Paz","America/Lima","America/Los_Angeles","America/Maceio","America/Managua","America/Manaus","America/Martinique","America/Matamoros","America/Mazatlan","America/Menominee","America/Merida","America/Metlakatla","America/Mexico_City","America/Miquelon","America/Moncton","America/Monterrey","America/Montevideo","America/New_York","America/Nome","America/Noronha","America/North_Dakota","America/North_Dakota","America/North_Dakota","America/Nuuk","America/Ojinaga","America/Panama","America/Paramaribo","America/Phoenix","America/Port","America/Porto_Velho","America/Puerto_Rico","America/Punta_Arenas","America/Rankin_Inlet","America/Recife","America/Regina","America/Resolute","America/Rio_Branco","America/Santarem","America/Santiago","America/Santo_Domingo","America/Sao_Paulo","America/Scoresbysund","America/Sitka","America/St_Johns","America/Swift_Current","America/Tegucigalpa","America/Thule","America/Tijuana","America/Toronto","America/Vancouver","America/Whitehorse","America/Winnipeg","America/Yakutat","Antarctica/Casey","Antarctica/Davis","Antarctica/Macquarie","Antarctica/Mawson","Antarctica/Palmer","Antarctica/Rothera","Antarctica/Troll","Asia/Almaty","Asia/Amman","Asia/Anadyr","Asia/Aqtau","Asia/Aqtobe","Asia/Ashgabat","Asia/Atyrau","Asia/Baghdad","Asia/Baku","Asia/Bangkok","Asia/Barnaul","Asia/Beirut","Asia/Bishkek","Asia/Chita","Asia/Choibalsan","Asia/Colombo","Asia/Damascus","Asia/Dhaka","Asia/Dili","Asia/Dubai","Asia/Dushanbe","Asia/Famagusta","Asia/Gaza","Asia/Hebron","Asia/Ho_Chi_Minh","Asia/Hong_Kong","Asia/Hovd","Asia/Irkutsk","Asia/Jakarta","Asia/Jayapura","Asia/Jerusalem","Asia/Kabul","Asia/Kamchatka","Asia/Karachi","Asia/Kathmandu","Asia/Khandyga","Asia/Kolkata","Asia/Krasnoyarsk","Asia/Kuching","Asia/Macau","Asia/Magadan","Asia/Makassar","Asia/Manila","Asia/Nicosia","Asia/Novokuznetsk","Asia/Novosibirsk","Asia/Omsk","Asia/Oral","Asia/Pontianak","Asia/Pyongyang","Asia/Qatar","Asia/Qostanay","Asia/Qyzylorda","Asia/Riyadh","Asia/Sakhalin","Asia/Samarkand","Asia/Seoul","Asia/Shanghai","Asia/Singapore","Asia/Srednekolymsk","Asia/Taipei","Asia/Tashkent","Asia/Tbilisi","Asia/Tehran","Asia/Thimphu","Asia/Tokyo","Asia/Tomsk","Asia/Ulaanbaatar","Asia/Urumqi","Asia/Ust","Asia/Vladivostok","Asia/Yakutsk","Asia/Yangon","Asia/Yekaterinburg","Asia/Yerevan","Atlantic/Azores","Atlantic/Bermuda","Atlantic/Canary","Atlantic/Cape_Verde","Atlantic/Faroe","Atlantic/Madeira","Atlantic/South_Georgia","Atlantic/Stanley","Australia/Adelaide","Australia/Brisbane","Australia/Broken_Hill","Australia/Darwin","Australia/Eucla","Australia/Hobart","Australia/Lindeman","Australia/Lord_Howe","Australia/Melbourne","Australia/Perth","Australia/Sydney")]
        [string]$Timezone,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$UserManagersCanPutUsersInBypass,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [int]$UserTelephonyCostMax


    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($GroupId,"Update Settings"))
        {
            [string]$apiPath = "/admin/v1/settings"

            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            if($PSBoundParameters.ContainsKey("CallerId"))
            {
                $parameter["caller_id"] = "$($CallerId)"
            }
            if($PSBoundParameters.ContainsKey("EmailActivityNotificationEnabled"))
            {
                $parameter["email_activity_notification_enabled"] = $($EmailActivityNotificationEnabled)
            }
            if($PSBoundParameters.ContainsKey("FraudEmail"))
            {
                $parameter["fraud_email"] = $($FraudEmail)
            }
            if($PSBoundParameters.ContainsKey("FraudEmailEnabled"))
            {
                $parameter["fraud_email_enabled"] = $($FraudEmailEnabled)
            }
            if($PSBoundParameters.ContainsKey("GlobalSspPolicyEnforced"))
            {
                $parameter["global_ssp_policy_enforced"] = $($GlobalSspPolicyEnforced)
            }
            if($PSBoundParameters.ContainsKey("HelpDeskBypass"))
            {
                $parameter["helpdesk_bypass"] = $($HelpDeskBypass)
            }
            if($PSBoundParameters.ContainsKey("HelpDeskExpirationMin"))
            {
                $parameter["helpdesk_bypass_expiration"] = $($HelpDeskExpirationMin)
            }
            if($PSBoundParameters.ContainsKey("HelpDeskCanSendEnrollEmail"))
            {
                $parameter["helpdesk_can_send_enroll_email"] = $($HelpDeskCanSendEnrollEmail)
            }
            if($PSBoundParameters.ContainsKey("InactiveUserExpirationDays"))
            {
                $parameter["inactive_user_expiration"] = $($InactiveUserExpirationDays)
            }
            if($PSBoundParameters.ContainsKey("KeyPressConfirm"))
            {
                $parameter["keypress_confirm"] = $($KeyPressConfirm)
            }
            if($PSBoundParameters.ContainsKey("KeyPressFraud"))
            {
                $parameter["keypress_fraud"] = $($KeyPressFraud)
            }
            if($PSBoundParameters.ContainsKey("Language"))
            {
                $parameter["language"] = $($Language)
            }
            if($PSBoundParameters.ContainsKey("LockoutExpireDurationMin"))
            {
                $parameter["lockout_expire_duration"] = $($LockoutExpireDurationMin)
            }
            if($PSBoundParameters.ContainsKey("LockoutThreshold"))
            {
                $parameter["lockout_threshold"] = $($LockoutThreshold)
            }
            if($PSBoundParameters.ContainsKey("LogRetentionDays"))
            {
                $parameter["log_retention_days"] = $($LogRetentionDays)
            }
            if($PSBoundParameters.ContainsKey("MinPasswordLength"))
            {
                $parameter["minimum_password_length"] = $($MinPasswordLength)
            }
            if($PSBoundParameters.ContainsKey("PasswordRequiresLowerAlpha"))
            {
                $parameter["password_requires_lower_alpha"] = $($PasswordRequiresLowerAlpha)
            }
            if($PSBoundParameters.ContainsKey("PasswordRequiresNumeric"))
            {
                $parameter["password_requires_numeric"] = $($PasswordRequiresNumeric)
            }
            if($PSBoundParameters.ContainsKey("PasswordRequiresSpecial"))
            {
                $parameter["password_requires_special"] = $($PasswordRequiresSpecial)
            }
            if($PSBoundParameters.ContainsKey("PasswordRequiresUpperAlpha"))
            {
                $parameter["password_requires_upper_alpha"] = $($PasswordRequiresUpperAlpha)
            }
            if($PSBoundParameters.ContainsKey("PushActivityNotificationEnabled"))
            {
                $parameter["push_activity_notification_enabled"] = $($PushActivityNotificationEnabled)
            }
            if($PSBoundParameters.ContainsKey("SmsBatch"))
            {
                $parameter["sms_batch"] = $($SmsBatch)
            }
            if($PSBoundParameters.ContainsKey("SmsExpirationMin"))
            {
                $parameter["sms_expiration"] = $($SmsExpirationMin)
            }
            if($PSBoundParameters.ContainsKey("SmsMessage"))
            {
                $parameter["sms_message"] = $($SmsMessage)
            }
            if($PSBoundParameters.ContainsKey("SmsRefresh"))
            {
                $parameter["sms_refresh"] = $($SmsRefresh)
            }
            if($PSBoundParameters.ContainsKey("TelephonyWarningMin"))
            {
                $parameter["telephony_warning_min"] = $($TelephonyWarningMin)
            }
            if($PSBoundParameters.ContainsKey("Timezone"))
            {
                $parameter["timezone"] = $($Timezone)
            }
            if($PSBoundParameters.ContainsKey("UserManagersCanPutUsersInBypass"))
            {
                $parameter["user_managers_can_put_users_in_bypass"] = $($UserManagersCanPutUsersInBypass)
            }
            if($PSBoundParameters.ContainsKey("UserTelephonyCostMax"))
            {
                $parameter["user_telephony_cost_max"] = $($UserTelephonyCostMax)
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Update-DuoSetting.ps1' 387
#Region './Public/Update-DuoUser.ps1' -1

function Update-DuoUser {
    <#
    .SYNOPSIS
    Update user with the specified username

    .DESCRIPTION
    Update user with the specified username

    .PARAMETER ApiHostname
    Target API hostname
    E.g. api-XXXXXXXX.duosecurity.com

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring

    .PARAMETER Username
    The name of the user to create

    .PARAMETER Email
    The email address of this user.

    .PARAMETER FullName
    The real name (or full name) of this user

    .PARAMETER Status
    The user's status. Allowed Values "active","bypass","disabled"
    "active" The user must complete secondary authentication. This is the default value if no status is specified.
    "bypass" The user will bypass secondary authentication after completing primary authentication.
    "disabled" The user will not be able to complete secondary authentication.

    .PARAMETER FirstName
    The user's given name.

    .PARAMETER LastName
    The user's surname

    .PARAMETER Notes
    An optional description or notes field. Can be viewed in the Duo Admin Panel

    .PARAMETER Aliases
    Username aliases for the user. Up to four aliases may be specified with this parameter.
    Aliases must be unique amongst users

    .PARAMETER AccountId
    Target account id. IF specified, the Credentials parameter must contain the account API credentials and URL.

    .PARAMETER UserId
    Target User ID

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Update-DuoUser -ApiHostname $ApiHostname -UseriD '0AS8FUA0SD89FA0SDF8' -Status 'bypass' -Credential $Credential -AccountId "AALSFLAJFKS5AJLKDJ55LA5KS"
    #>

    [cmdletbinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
    param(
        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [pscredential]$Credential,

        [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$UserId,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Username,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Email,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$FullName,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateSet("active", "bypass","disabled")]
        [string]$Status,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$FirstName,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$LastName,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$Notes,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [ValidateLength(1,4)]
        [array]$Aliases,

        [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
        [string]$AccountId
    )
    Begin{
        [array]$output = @()
        [hashtable]$parameter = @{}

    }
    Process{
        if($PSCmdlet.ShouldProcess($UserId, "Update user"))
        {
            [string]$apiPath = "/admin/v1/users/$($UserId)"
            if($PSBoundParameters.ContainsKey("Username"))
            {
                $parameter["username"] = "$($Username)"
            }
            if($PSBoundParameters.ContainsKey("Email"))
            {
                $parameter["email"] = "$($Email)"
            }
            if($PSBoundParameters.ContainsKey("FullName"))
            {
                $parameter["realname"] = "$($FullName)"
            }
            if($PSBoundParameters.ContainsKey("Status"))
            {
                $parameter["status"] = "$($Status)"
            }
            if($PSBoundParameters.ContainsKey("FirstName"))
            {
                $parameter["firstname"] = "$($FirstName)"
            }
            if($PSBoundParameters.ContainsKey("LastName"))
            {
                $parameter["lastname"] = "$($LastName)"
            }
            if($PSBoundParameters.ContainsKey("Notes"))
            {
                $parameter["notes"] = "$($Notes)"
            }
            if($PSBoundParameters.ContainsKey("Aliases"))
            {
                for($i = 1; $i -lt $Aliases.Length; $i ++) {
                    $parameter["alias$i"] = $Aliases[$i]
                }
            }
            if($PSBoundParameters.ContainsKey("AccountId"))
            {
                $parameter["account_id"] = "$($AccountId)"
            }
            do{
                $temp = Invoke-DuoApi -ApiPath $apiPath -Method POST -ApiHostname $ApiHostname -Credential $($Credential) -ApiParams $parameter
                $output += $temp.response
                $parameter["offset"] = "$($temp.metadata.next_offset)"
            }
            while($temp.metadata.next_offset)
        }
    }
    End{
        return $Output
    }
}
#EndRegion './Public/Update-DuoUser.ps1' 154