Public/DuoTokenFunctions.ps1
Function Get-DuoToken { <# .SYNOPSIS Retrieves Duo token information. .DESCRIPTION This function retrieves information about Duo tokens based on the provided parameters. It can fetch tokens by TokenID or by Serial and Type. .PARAMETER TokenID The ID of the token to retrieve. This parameter is optional and can be piped. .PARAMETER Serial The serial number of the token. This parameter is optional. .PARAMETER Type The type of the token. Valid values are "HOTP-6", "HOTP-8", "YubiKey", and "Duo-D100". This parameter is mandatory when Serial is specified. .LINK https://github.com/jyates2006/PSDuo https://jaredyatesit.com/Documentation/PSDuo #> [CmdletBinding(DefaultParameterSetName="TID")] PARAM( [Parameter(ParameterSetName="TID", Mandatory = $false, ValueFromPipeLine = $true, Position=0 )] [ValidateScript({ If(Test-DuoTokens -TokenID $_){$true} Else{Throw "Token: $($_) doesn't exist in Duo"} })] [String]$TokenID, [Parameter(ParameterSetName="Tserial", Mandatory = $false, ValueFromPipeLine = $false, Position=0 )] [String]$Serial, [Parameter(ParameterSetName="Tserial", Mandatory = $true, ValueFromPipeLine = $false, Position=1 )] [ValidateSet("HOTP-6","HOTP-8","YubiKey","Duo-D100")] [String]$Type ) #Base claim [String]$Method = "GET" [String]$Uri = "/admin/v1/tokens" [Hashtable]$DuoParams = @{} If($Serial){ $DuoParams.Add("serial",$serial.ToLower()) Switch($Type){ "HOTP-6" {$DuoParams.Add("type","h6")} "HOTP-8" {$DuoParams.Add("type","h8")} "YubiKey" {$DuoParams.Add("type","yk")} "Duo-D100" {$DuoParams.Add("type","d1")} } } ElseIf($TokenID){ $Uri = "/admin/v1/tokens/$($TokenID)" } Else{ $DuoParams.Add("limit","300") $DuoParams.Add("offset","0") } $Offset = 0 #Duo has a 300 user limit in their api. Loop to return all users Do{ $DuoParams.Offset = $Offset $Request = New-DuoRequest -UriPath $Uri -Method $Method -Arguments $DuoParams $Response = Invoke-RestMethod @Request If($Response.stat -ne 'OK'){ Write-Warning 'DUO REST Call Failed' Write-Warning "Arguments:"+($DuoParams | Out-String) Write-Warning "Method:$Method Path:$Uri" } Else{ $Output = $Response | Select-Object -ExpandProperty Response $Output #Increment offset to return the next 300 users $Offset += 300 } }Until($Output.Count -lt 300) } Function New-DuoToken { <# .SYNOPSIS Creates a new Duo token. .DESCRIPTION This function creates a new Duo token using the specified parameters. .PARAMETER Serial The serial number of the token. .PARAMETER HOTP6 Specifies that the token type is HOTP-6. .PARAMETER HOTP8 Specifies that the token type is HOTP-8. .PARAMETER Secret The secret key for HOTP tokens. .PARAMETER PrivateID The private ID for YubiKey tokens. .PARAMETER AESkey The AES key for YubiKey tokens. .PARAMETER Counter The counter value for HOTP tokens. .LINK https://github.com/jyates2006/PSDuo https://jaredyatesit.com/Documentation/PSDuo #> PARAM( [Parameter( Mandatory = $true, ValueFromPipeLine = $false, Position = 0 )] [String]$Serial, [Parameter(ParameterSetName = "HOTP-6", Mandatory = $true, ValueFromPipeLine = $false, Position = 1 )] [Switch]$HOTP6, [Parameter(ParameterSetName = "HOTP8", Mandatory = $true, ValueFromPipeLine = $false, Position = 1 )] [Switch]$HOTP8, [Parameter(ParameterSetName = "HOTP6", Mandatory = $true, ValueFromPipeLine = $false, Position = 2 )] [Switch]$SecretHOTP6, [Parameter(ParameterSetName = "HOTP8", Mandatory = $true, ValueFromPipeLine = $false, Position = 2 )] [Switch]$SecretHOTP8, [Parameter(ParameterSetName = "YubiKey", Mandatory = $true, ValueFromPipeLine = $false, Position = 1 )] [Switch]$PrivateID, [Parameter(ParameterSetName = "HOTP6", Mandatory = $false, ValueFromPipeLine = $false, Position = 3 )] [Switch]$CounterHOTP6, [Parameter(ParameterSetName = "HOTP8", Mandatory = $false, ValueFromPipeLine = $false, Position = 3 )] [Switch]$CounterHOTP8, [Parameter(ParameterSetName = "YubiKey", Mandatory = $true, ValueFromPipeLine = $false, Position = 2 )] [Switch]$AESkey ) #Base claim [String]$Method = "POST" [String]$Uri = "/admin/v1/tokens" [Hashtable]$DuoParams = @{} If($HOTP6){ $Type = "h6" } ElseIf($HOTP8){ $Type = "h8" } ElseIf($YubiKey){ $Type = "yk" } $DuoParams.Add("type",$Type) $DuoParams.Add("serial",$Serial) If($HOTP6 -or $HOTP8){ $DuoParams.Add("secret",$Secret) If($Counter){ $DuoParams.Add("counter",$Counter.ToString()) } } ElseIf($YubiKey){ $DuoParams.Add("private_id",$PrivateID) $DuoParams.Add("aes_key",$AESkey) } $Request = New-DuoRequest -UriPath $Uri -Method $Method -Arguments $DuoParams $Response = Invoke-RestMethod @Request If($Response.stat -ne 'OK'){ Write-Warning 'DUO REST Call Failed' Write-Warning "Arguments:"+($DuoParams | Out-String) Write-Warning "Method:$Method Path:$Uri" } Else{ $Output = $Response | Select-Object -ExpandProperty Response $Output } } Function Sync-DuoToken { <# .SYNOPSIS Synchronizes a token with Duo. .DESCRIPTION This function sends a POST request to the Duo Admin API to synchronize a token specified by its TokenID or Serial and Type. It requires three codes generated by the token for synchronization. .PARAMETER Serial The serial number of the token to be synchronized. .PARAMETER TokenID The ID of the token to be synchronized. .PARAMETER Code1 The first code generated by the token. .PARAMETER Code2 The second code generated by the token. .PARAMETER Code3 The third code generated by the token. .PARAMETER Type The type of the token to be synchronized. Valid values are "HOTP-6", "HOTP-8", and "Duo-D100". .EXAMPLE PS C:\> Sync-DuoToken -TokenID "token123" -Code1 "123456" -Code2 "234567" -Code3 "345678" .EXAMPLE PS C:\> Sync-DuoToken -Serial "serial123" -Type "HOTP-6" -Code1 "123456" -Code2 "234567" -Code3 "345678" .LINK https://github.com/jyates2006/PSDuo https://jaredyatesit.com/Documentation/PSDuo .NOTES Ensure you have the necessary permissions and API keys to interact with the Duo Admin API. #> [CmdletBinding(DefaultParameterSetName="TID")] PARAM( [Parameter(ParameterSetName="Serial", Mandatory = $true, ValueFromPipeLine = $false, Position=0 )] [String]$Serial, [Parameter(ParameterSetName="TID", Mandatory = $true, ValueFromPipeLine = $false, Position=0 )] [ValidateScript({ If(Test-DuoTokens -TokenID $_){$true} Else{Throw "Token: $($_) doesn't exist in Duo"} })] [String]$TokenID, [Parameter( Mandatory = $true, ValueFromPipeLine = $false, Position=2 )] [String]$Code1, [Parameter( Mandatory = $true, ValueFromPipeLine = $false, Position=3 )] [String]$Code2, [Parameter( Mandatory = $true, ValueFromPipeLine = $false, Position=4 )] [String]$Code3, [Parameter(ParameterSetName="Serial", Mandatory = $true, ValueFromPipeLine = $false, Position=1 )] [ValidateSet("HOTP-6","HOTP-8","Duo-D100")] [String]$Type ) If($Serial){ $TokenID = (Get-DuoTokens -Serial $Serial -Type $Type).token_id } #Base claim [String]$Method = "POST" [String]$Uri = "/admin/v1/tokens/$($TokenID)" [Hashtable]$DuoParams = @{} $DuoParams.Add("code1",$Code1) $DuoParams.Add("code2",$Code2) $DuoParams.Add("code3",$Code3) $Request = New-DuoRequest -UriPath $Uri -Method $Method -Arguments $DuoParams $Response = Invoke-RestMethod @Request If($Response.stat -ne 'OK'){ Write-Warning 'DUO REST Call Failed' Write-Warning "Arguments:"+($DuoParams | Out-String) Write-Warning "Method:$Method Path:$Uri" } Else{ $Output = $Response | Select-Object -ExpandProperty Response $Output } } Function Remove-DuoToken { <# .SYNOPSIS Removes a token from Duo. .DESCRIPTION This function sends a DELETE request to the Duo Admin API to remove a token specified by its TokenID or Serial and Type. .PARAMETER TokenID The ID of the token to be removed. .PARAMETER Serial The serial number of the token to be removed. .PARAMETER Type The type of the token to be removed. Valid values are "HOTP-6", "HOTP-8", "YubiKey", and "Duo-D100". .EXAMPLE PS C:\> Remove-DuoToken -TokenID "token123" .EXAMPLE PS C:\> Remove-DuoToken -Serial "serial123" -Type "YubiKey" .LINK https://github.com/jyates2006/PSDuo https://jaredyatesit.com/Documentation/PSDuo .NOTES Ensure you have the necessary permissions and API keys to interact with the Duo Admin API. #> [CmdletBinding(DefaultParameterSetName="TID")] PARAM( [Parameter(ParameterSetName="TID", Mandatory = $true, ValueFromPipeLine = $false, Position=0 )] [ValidateScript({ If(Test-DuoTokens -TokenID $_){$true} Else{Throw "Token: $($_) doesn't exist in Duo"} })] [String]$TokenID, [Parameter(ParameterSetName="Serial", Mandatory = $true, ValueFromPipeLine = $false, Position=0 )] [String]$Serial, [Parameter(ParameterSetName="Serial", Mandatory = $true, ValueFromPipeLine = $false, Position=1 )] [ValidateSet("HOTP-6","HOTP-8","YubiKey","Duo-D100")] [String]$Type ) If($Serial){ $TokenID = Get-DuoTokens -Serial $Serial -Type $Type } #Base claim [String]$Method = "DELETE" [String]$Uri = "/admin/v1/tokens/$($TokenID)" [Hashtable]$DuoParams = @{} $Request = New-DuoRequest -UriPath $Uri -Method $Method -Arguments $DuoParams $Response = Invoke-RestMethod @Request If($Response.stat -ne 'OK'){ Write-Warning 'DUO REST Call Failed' Write-Warning "Arguments:"+($DuoParams | Out-String) Write-Warning "Method:$Method Path:$Uri" } Else{ $Output = $Response | Select-Object -ExpandProperty Response $Output } } Function Get-DuoWebAuthnCredential { <# .SYNOPSIS Retrieves WebAuthn credentials from Duo. .DESCRIPTION This function sends a GET request to the Duo Admin API to retrieve details of WebAuthn credentials. It supports retrieving a specific WebAuthn credential by WebAuthnKey or all WebAuthn credentials with pagination. .PARAMETER WebAuthnKey The key of the WebAuthn credential to retrieve. If not specified, retrieves all WebAuthn credentials. .EXAMPLE PS C:\> Get-DuoWebAuthnCredential .EXAMPLE PS C:\> Get-DuoWebAuthnCredential -WebAuthnKey "webauthn123" .LINK https://github.com/jyates2006/PSDuo https://jaredyatesit.com/Documentation/PSDuo .NOTES Ensure you have the necessary permissions and API keys to interact with the Duo Admin API. #> PARAMS( [Parameter( Mandatory = $false, ValueFromPipeLine = $true, Position=0 )] [ValidateScript({ If(Test-DuoWEbAuthnKey -TokenID $_){$true} Else{Throw "Token: $($_) doesn't exist in Duo"} })] [String]$WebAuthnKey ) #Base claim [String]$Method = "GET" [String]$Uri = "/admin/v1/webauthncredentials" [Hashtable]$DuoParams = @{} If($WebAuthnKey){ $Uri = "/admin/v1/webauthncredentials/$($WebAuthnKey)" } $Offset = 0 #Duo has a 300 user limit in their api. Loop to return all users Do{ $DuoParams.Offset = $Offset $Request = New-DuoRequest -UriPath $Uri -Method $Method -Arguments $DuoParams $Response = Invoke-RestMethod @Request If($Response.stat -ne 'OK'){ Write-Warning 'DUO REST Call Failed' Write-Warning "Arguments:"+($DuoParams | Out-String) Write-Warning "Method:$Method Path:$Uri" } Else{ $Output = $Response | Select-Object -ExpandProperty Response $Output #Increment offset to return the next 300 users $Offset += 300 } }Until($Output.Count -lt 300) } Function Remove-DuoWebAuthnCredential { <# .SYNOPSIS Removes a WebAuthn credential from Duo. .DESCRIPTION This function sends a DELETE request to the Duo Admin API to remove a WebAuthn credential specified by its WebAuthnKey. .PARAMETER WebAuthnKey The key of the WebAuthn credential to be removed. .EXAMPLE PS C:\> Remove-DuoWebAuthnCredential -WebAuthnKey "webauthn123" .LINK https://github.com/jyates2006/PSDuo https://jaredyatesit.com/Documentation/PSDuo .NOTES Ensure you have the necessary permissions and API keys to interact with the Duo Admin API. #> PARAMS( [Parameter( Mandatory = $false, ValueFromPipeLine = $true, Position=0 )] [ValidateScript({ If(Test-DuoWEbAuthnKey -TokenID $_){$true} Else{Throw "Token: $($_) doesn't exist in Duo"} })] [String]$WebAuthnKey ) #Base claim [String]$Method = "DELETE" [String]$Uri = "/admin/v1/webauthncredentials/$($WebAuthnKey)" [Hashtable]$DuoParams = @{} $Request = New-DuoRequest -UriPath $Uri -Method $Method -Arguments $DuoParams $Response = Invoke-RestMethod @Request If($Response.stat -ne 'OK'){ Write-Warning 'DUO REST Call Failed' Write-Warning "Arguments:"+($DuoParams | Out-String) Write-Warning "Method:$Method Path:$Uri" } Else{ $Output = $Response | Select-Object -ExpandProperty Response $Output } } |