private/Convertto-DUORequest.ps1
|
<# .Synopsis DUO Webrequest Authentication Generator .DESCRIPTION DUO API Authentication Helper DUO Authentication calls require a specific format: The API uses HTTP Basic Authentication to authenticate requests. Use your Duo application’s integration key as the HTTP Username. Generate the HTTP Password as an HMAC signature of the request. This will be different for each request and must be re-generated each time. .EXAMPLE [string]$method = "GET" [string]$path = "/admin/v1/users" $APiParams = @{username='JoeTheUser'} $DuoRequest = Convertto-DUORequest -DuoMethodPath $path -Method $method -ApiParams $ApiParams Invoke-RestMethod @DuoRequest .INPUTS .OUTPUTS .NOTES DUO API Authentication The API uses HTTP Basic Authentication to authenticate requests. Use your Duo application’s integration key as the HTTP Username. Generate the HTTP Password as an HMAC signature of the request. This will be different for each request and must be re-generated each time. https://duo.com/docs/adminapi#authentication Return HTTP Basic Authentication ("Authorization" and "Date") headers. method, host, path: strings from request $method = 'GET -or PLACE...' $apiHost = 'api-xxxxxxxx.duosecurity.com' $DuoMethodPath = '/admin/v1/users' $StringAPIParams - Converted locally, using passed vairables from commandlets *Some of DUO's path enpoints include the only parameter needed and therefore do not need $StringAPIParams. params: dict of request parameters $APIParams skey: secret key $DuoConfig.sKey ikey: integration key $DuoConfig.iKey $DUOmethodPath .COMPONENT DUOPS .FUNCTIONALITY DUO API #> function Convertto-DuoRequest(){ param( $DuoMethodPath, $APIParams, $method ) #Decrypt our keys from our config $skey = $DUOSecretKey $iKey = $DUOIntegrationKey $apiHost = $DUOApiHost [cultureinfo]$culture = [CultureInfo]'en-uk' $date = (Get-Date).ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss -0000", $culture) #Stringified Params/URI Safe chars - I think this should grab everything... $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(), $DuoMethodPath.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 = @{ ContentType = 'application/x-www-form-urlencoded' Method = $method Body = $APIParams Headers = @{ "X-Duo-Date" = $Date "Authorization" = ('Basic: {0}' -f [System.Convert]::ToBase64String($ASCIBytes)) } URI = ('Https://{0}{1}' -f $apiHost, $DuoMethodPath) } Write-Output $DUOWebRequestParams } |