Oleg Usmanov
Oleg Usmanov

Reputation: 43

Azure DocumentDB Rest API PowerShell delete collection 401 Unathorized

Need to delete collection in my automation process. Trying to execute script below. Get operations working fine, but Delete operation failed with "(401) Unathorized" error. It is strange cause Delete collection do not need additional headers. Can someone give a hint, what is wrong?

$accountName  = 'someaccountname'
$connectionKey = 'masterkey'
$collectionName = 'mycollection'
$databaseName = 'mydatabase'

function GetKey([System.String]$Verb = '',[System.String]$ResourceId = '',
        [System.String]$ResourceType = '',[System.String]$Date = '',[System.String]$masterKey = '') {
    $keyBytes = [System.Convert]::FromBase64String($masterKey) 
    $text = @($Verb.ToLowerInvariant() + "`n" + $ResourceType.ToLowerInvariant() + "`n" + $ResourceId + "`n" + $Date.ToLowerInvariant() + "`n" + "`n")
    $body =[Text.Encoding]::UTF8.GetBytes($text)
    $hmacsha = new-object -TypeName System.Security.Cryptography.HMACSHA256 -ArgumentList (,$keyBytes) 
    $hash = $hmacsha.ComputeHash($body)
    $signature = [System.Convert]::ToBase64String($hash)
    [System.Web.HttpUtility]::UrlEncode($('type=master&ver=1.0&sig=' + $signature))
}
 function BuildHeaders([string]$action = "get",[string]$resType, [string]$resourceId){
    $authz = GetKey -Verb $action -ResourceType $resType -ResourceId $resourceId -Date $apiDate -masterKey $connectionKey
    $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $headers.Add("Authorization", $authz)
    $headers.Add("x-ms-version", '2015-12-16')
    $headers.Add("x-ms-date", $apiDate) 
    $headers
}
function GetUTDate() {
    $date = get-date
    $date = $date.ToUniversalTime();
    return $date.ToString("r", [System.Globalization.CultureInfo]::InvariantCulture);
}
function GetDatabases() {
    $uri = $rootUri + "/dbs"
    $hdr = BuildHeaders -resType dbs
    $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $hdr
    $response.Databases
    Write-Host ("Found " + $Response.Databases.Count + " Database(s)")
}
function GetCollections([string]$dbname){
    $uri = $rootUri + "/" + $dbname + "/colls"
    $hdr = BuildHeaders -resType colls -resourceId $dbname
    $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $hdr
    $response.DocumentCollections
    Write-Host ("Found " + $Response.DocumentCollections.Count + " DocumentCollection(s)")
}
function DeleteCollection([string]$dbname){
    $uri = $rootUri + "/" + $dbname + "/colls" + "/" + $collectionName
    $hdrs = BuildHeaders -action DELETE -resType colls -resourceId $collectionName
    $response = Invoke-RestMethod -Uri $uri -Method Delete -Headers $hdrs
    Write-Host "DELETE $uri"
}
$rootUri = "https://" + $accountName + ".documents.azure.com"
write-host ("Root URI is " + $rootUri)

#validate arguments
$apiDate = GetUTDate
$db = GetDatabases | where { $_.id -eq $databaseName }

if ($db -eq $null) {
    write-error "Could not find database in account"
    return
} 

$dbname = "dbs/" + $databaseName
$collection = GetCollections -dbname $dbname | where { $_.id -eq $collectionName }

if($collection -eq $null){
    write-error "Could not find collection in database"
    return
}
Write-Host
$Delete = DeleteCollection -dbname $dbname | where { $_.id -eq $collectionName } 

Upvotes: 0

Views: 745

Answers (2)

Fei Han
Fei Han

Reputation: 27803

Normally, either the Authorization or x-ms-date header is not set (or the Authorization header with an invalid authorization token), 401 unauthorized error will be returned. I use fiddler to capture the request and check the response, and I find both Authorization and x-ms-date header are set, so it seems that the Authorization header is set to an invalid authorization token. Based on your code, I do some changes, and the function could work fine on my side.

function DeleteCollection([string]$dbname){
    $uri = $rootUri + "/" + $dbname + "/colls" + "/" + $collectionName
    $collectionName = $dbname + "/colls" + "/" + $collectionName
    $hdrs = BuildHeaders -action DELETE -resType colls -resourceId $collectionName
    #Write-Host "resourceId $collectionName"
    $response = Invoke-RestMethod -Uri $uri -Method Delete -Headers $hdrs
    Write-Host "resource $collectionName"
    Write-Host "DELETE $uri"
} 

The $collectionName should be dbs/{yourdbname}/colls/{yourcollectionname}

enter image description here

Upvotes: 2

Larry Maccherone
Larry Maccherone

Reputation: 9533

This can happen if there are pending operations. Either retry until it succeeds or add a delay before deleting. For us, a half second is enough to assure we never see this again.

Upvotes: 1

Related Questions