Skip to content

PSDuo

about_PSDuo

This PowerShell module streamlines the administration of DUO users and devices, enabling automated configuration for efficient setup. Ideal for release pipelines, it simplifies anagement and ensures consistent deployment.

SHORT DESCRIPTION

Powershell Wrapper for the DUO APIs.

EXAMPLES

The example below shows how the module can be used to get user information

Warning

You must use IKEY for the username and SKEY for the password when creating a pscredential

$IKEY = xxxxx-xxxxxxxx-xxxxxxx-xxxxxxx
$SKEY = xxxxxx-xxxxxxxxx-xxxxxxxx-xxxxxxxxxx
$secString = ConvertTo-SecureString -String $SKEY -AsPlainText -Force
$Credential = [pscredential]::new($IKEY,$secString)

Example

Get-DuoUserInformation.ps1
[CmdletBinding()]
param (
    [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)]
    [string]$TenantName,

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

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

    [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
    [string]$ApiHostname
)
begin {
    $Auth = @{
        ApiHostname = $ApiHostname
        Credential = $Credential
    }
    [array]$Output = @()
}
process {

    if(($PSBoundParameters.ContainsKey("TenantName")))
    {
        $Accounts = Get-DuoAccount @Auth
        $target = $Accounts | Where-Object {$PSItem.Name -ieq $TenantName}
        if(-not ($target))
        {
            Write-Error "Account '$TenantName' was not found"
        }
        $Auth["AccountId"] = $target.account_id

    }
    if($PSBoundParameters.containskey("Username"))
    {
        $Auth["Username"] = $Username
    }
    $users = Get-DuoUser @Auth
    foreach($user in $users) {
        [array]$phones = @()
        foreach($phone in $user.phones) {
            $phones += [pscustomobject]@{
                Activeted = $phone.activated
                Name = $phone.Name
                Number = $phone.Number
                LastSeen = $phone.last_seen
            }
        }
        $Output += [pscustomobject]@{
            Username = $user.username
            Status = $user.status
            LastLogin = $(ConvertFrom-Epoch -Date  $user.last_login)
            Email = $user.email
            Phones = $phones
        }
    }
}
end {
    return $Output
}
Get-DuoUserInformation
function Get-DuoUserInformation {
    <#
    .SYNOPSIS
    Get Duo User information

    .DESCRIPTION
    Get Duo User information

    .PARAMETER TenantName
    Target Tenant Name

    .PARAMETER Username
    Target username

    .PARAMETER Credential
    PSCredential containing IKEY as username and SKEY as securestring
    When Tenant Name is not specified, the Credential must be for the AdminAPI

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

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoUserInformation -Credential $Credential -ApiHostname $ApiHostname -Username 'bob'

    .EXAMPLE
    PS>$Credential = $(Get-SecureCredential -Name 'DUO_Account' -VaultName 'vault')
    PS>$ApiHostname = "api-XXXXXXXX.duosecurity.com"
    PS>Get-DuoUserInformation -Credential $Credential -ApiHostname $ApiHostname -Username 'bob' -TenantName 'MyTenant'
    #>
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)]
        [string]$TenantName,

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

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

        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [string]$ApiHostname
    )
    begin {
        $Auth = @{
            ApiHostname = $ApiHostname
            Credential = $Credential
        }
        [array]$Output = @()
    }
    process {

        if(($PSBoundParameters.ContainsKey("TenantName")))
        {
            $Accounts = Get-DuoAccount @Auth
            $target = $Accounts | Where-Object {$PSItem.Name -ieq $TenantName}
            if(-not ($target))
            {
                Write-Error "Account '$TenantName' was not found"
            }
            $Auth["AccountId"] = $target.account_id

        }
        if($PSBoundParameters.containskey("Username"))
        {
            $Auth["Username"] = $Username
        }
        $users = Get-DuoUser @Auth
        foreach($user in $users) {
            [array]$phones = @()
            foreach($phone in $user.phones) {
                $phones += [pscustomobject]@{
                    Activeted = $phone.activated
                    Name = $phone.Name
                    Number = $phone.Number
                    LastSeen = $phone.last_seen
                }
            }
            $Output += [pscustomobject]@{
                Username = $user.username
                Status = $user.status
                LastLogin = $(ConvertFrom-Epoch -Date  $user.last_login)
                Email = $user.email
                Phones = $phones
            }
        }
    }
    end {
        return $Output
    }
}

Execution

$IKEY = xxxxx-xxxxxxxx-xxxxxxx-xxxxxxx
$SKEY = xxxxxx-xxxxxxxxx-xxxxxxxx-xxxxxxxxxx
$secString = ConvertTo-SecureString -String $SKEY -AsPlainText -Force
$Credential = [pscredential]::new($IKEY,$secString)
$ApiHostname = "api-XXXXXXXX.duosecurity.com"
.\Get-DuoUserInformation.ps1 -Credential $Credential -ApiHostname $ApiHostname -Username 'bob'
$IKEY = xxxxx-xxxxxxxx-xxxxxxx-xxxxxxx
$SKEY = xxxxxx-xxxxxxxxx-xxxxxxxx-xxxxxxxxxx
$secString = ConvertTo-SecureString -String $SKEY -AsPlainText -Force
$Credential = [pscredential]::new($IKEY,$secString)
$ApiHostname = "api-XXXXXXXX.duosecurity.com"
Get-DuoUserInformation -Credential $Credential -ApiHostname $ApiHostname -Username 'bob'

NOTE

This PowerShell module is provided "as-is" without any guarantees or warranty. Use it at your own risk. The authors and contributors are not responsible for any damage or issues that may arise from using this module.

LICENSE

This project is under the MIT license.

KEYWORDS

  • DUO
  • MFA