Created
November 11, 2023 14:12
-
-
Save RylandDeGregory/ab21955d990a5f6ff649c29d34cca858 to your computer and use it in GitHub Desktop.
Azure Cosmos DB (NoSQL API) REST operations using PowerShell.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function New-MasterKeyAuthorizationSignature { | |
<# | |
.SYNOPSIS | |
Generate Cosmos DB Master Key Authentication header for use with the NoSQL REST API. | |
.EXAMPLE | |
$AuthKeyParams = @{ | |
Method = Post | |
ResourceId = "dbs/$DatabaseId/colls/$CollectionId" | |
Date = [DateTime]::UtcNow.ToString('r') | |
MasterKey = $MasterKey | |
} | |
$AuthorizationKey = New-MasterKeyAuthorizationSignature @AuthKeyParams | |
#> | |
[OutputType([string])] | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory)] | |
[ValidateSet( | |
'Get', | |
'Post', | |
'Put', | |
'Patch', | |
'Delete' | |
)] | |
[string] $Method, | |
[Parameter(Mandatory)] | |
[string] $ResourceId, | |
[Parameter()] | |
[string] $ResourceType = 'docs', | |
[Parameter(Mandatory)] | |
[string] $Date, | |
[Parameter(Mandatory)] | |
[string] $MasterKey | |
) | |
$KeyType = 'master' | |
$TokenVersion = '1.0' | |
$SigningString = "$($Method.ToLower())`n$($ResourceType.ToLower())`n$ResourceId`n$($Date.ToString().ToLower())`n`n" | |
$HmacSha = [System.Security.Cryptography.HMACSHA256]@{ Key = [Convert]::FromBase64String($MasterKey) } | |
$Signature = [Convert]::ToBase64String($HmacSha.ComputeHash([Text.Encoding]::UTF8.GetBytes($SigningString))) | |
$AuthorizationString = [System.Web.HttpUtility]::UrlEncode('type=' + $KeyType + '&ver=' + $TokenVersion + '&sig=' + $Signature) | |
$HmacSha.Dispose() | |
return $AuthorizationString | |
} | |
function New-Sha256HashedString { | |
<# | |
.SYNOPSIS | |
Generate the SHA256 hash of a string | |
.EXAMPLE | |
New-Sha256HashedString -String 'Hello' | |
#> | |
[OutputType([string])] | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory)] | |
[string] $String | |
) | |
$Sha256 = [System.Security.Cryptography.HashAlgorithm]::Create('SHA256') | |
$HashedBytes = $Sha256.ComputeHash([Text.Encoding]::UTF8.GetBytes($String)) | |
$HashedString = [BitConverter]::ToString($HashedBytes) -replace '-', '' | |
$Sha256.Dispose() | |
return $HashedString.ToLower() | |
} | |
function New-CosmosDocument { | |
<# | |
.SYNOPSIS | |
Create a new Cosmos DB NoSQL API document using the REST API. Uses Master Key Authentication. | |
.LINK | |
New-MasterKeyAuthorizationSignature | |
.EXAMPLE | |
$NewDocParams = @{ | |
Endpoint = 'https://xxxxx.documents.azure.com:443/' | |
MasterKey = $MasterKey | |
ResourceId = "dbs/$DatabaseId/colls/$CollectionId" | |
PartitionKey = $PartitionKey | |
PartitionKeyValue = $PartitionKeyValue | |
Document = @{property1 = 'value1'; property2 = @('value1', 'value2')} ## Any valid PSObject | |
} | |
New-CosmosDocument @NewDocParams | |
#> | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory)] | |
[string] $Endpoint, | |
[Parameter(Mandatory)] | |
[string] $MasterKey, | |
[Parameter(Mandatory)] | |
[string] $ResourceId, | |
[Parameter()] | |
[string] $ResourceType = 'docs', | |
[Parameter(Mandatory)] | |
[string] $PartitionKey, | |
[Parameter(Mandatory)] | |
[string] $PartitionKeyValue, | |
[Parameter(Mandatory)] | |
[psobject] $Document, | |
# Whether to treat the insert operation as an update | |
# if the Document ID already exists in the Collection | |
[Parameter()] | |
[boolean] $IsUpsert = $true | |
) | |
# Calculate current date for use in Authorization header | |
$Date = [DateTime]::UtcNow.ToString('r') | |
# Compute Authorization header value and define headers dictionary | |
$AuthorizationKey = New-MasterKeyAuthorizationSignature -Method Post -ResourceId $ResourceId -Date $Date -MasterKey $MasterKey | |
$Headers = @{ | |
'accept' = 'application/json' | |
'authorization' = $AuthorizationKey | |
'cache-control' = 'no-cache' | |
'content-type' = 'application/json' | |
'x-ms-date' = $Date | |
'x-ms-documentdb-partitionkey' = "[`"$PartitionKeyValue`"]" | |
'x-ms-version' = '2018-12-31' | |
} | |
if ($IsUpsert) { | |
$Headers += @{'x-ms-documentdb-is-upsert' = $true} | |
} | |
# Add Partition Key | |
Add-Member -InputObject $Document -MemberType NoteProperty -Name $PartitionKey -Value $PartitionKeyValue | |
# Add Document ID | |
if ($Document.id) { $Document.PSObject.Properties.Remove('id') } | |
$DocumentId = New-Sha256HashedString -String ($Document | ConvertTo-Json -Depth 15) # Use any deterministic value | |
Add-Member -InputObject $Document -MemberType NoteProperty -Name 'id' -Value $DocumentId | |
# Send request to NoSQL REST API | |
try { | |
$Response = Invoke-RestMethod -Uri "$Endpoint$ResourceId/$ResourceType" -Headers $Headers -Method Post -Body ($Document | ConvertTo-Json -Depth 15) | |
@{ | |
id = $Response.id | |
$PartitionKey = $Response.$PartitionKey | |
etag = $Response.'_etag' | |
timestamp = $Response.'_ts' | |
} | |
} catch { | |
Write-Error "StatusCode: $($_.Exception.Response.StatusCode.value__) | ExceptionMessage: $($_.Exception.Message) | $_" | |
} | |
} | |
function Get-CosmosDocument { | |
<# | |
.SYNOPSIS | |
Retrieve a Cosmos DB NoSQL API document by ID using the REST API. Uses Master Key Authentication. | |
.LINK | |
New-MasterKeyAuthorizationSignature | |
.EXAMPLE | |
$GetDocParams = @{ | |
Endpoint = 'https://xxxxx.documents.azure.com:443/' | |
MasterKey = $MasterKey | |
ResourceId = "dbs/$DatabaseId/colls/$CollectionId" | |
DocumentId = $DocumentId | |
PartitionKeyValue = $PartitionKeyValue | |
} | |
Get-CosmosDocument @GetDocParams | |
#> | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory)] | |
[string] $Endpoint, | |
[Parameter(Mandatory)] | |
[string] $MasterKey, | |
[Parameter(Mandatory)] | |
[string] $ResourceId, | |
[Parameter(Mandatory)] | |
[string] $DocumentId, | |
[Parameter()] | |
[string] $ResourceType = 'docs', | |
[Parameter(Mandatory)] | |
[string] $PartitionKeyValue | |
) | |
# Calculate current date for use in Authorization header | |
$Date = [DateTime]::UtcNow.ToString('r') | |
# Compute Authorization header value and define headers dictionary | |
$AuthorizationKey = New-MasterKeyAuthorizationSignature -Method Get -ResourceId "$ResourceId/$ResourceType/$DocumentId" -Date $Date -MasterKey $MasterKey | |
$Headers = @{ | |
'accept' = 'application/json' | |
'authorization' = $AuthorizationKey | |
'cache-control' = 'no-cache' | |
'content-type' = 'application/json' | |
'x-ms-date' = $Date | |
'x-ms-documentdb-partitionkey' = "[`"$PartitionKeyValue`"]" | |
'x-ms-version' = '2018-12-31' | |
} | |
# Send request to NoSQL REST API | |
try { | |
Invoke-RestMethod -Uri "$Endpoint$ResourceId/$ResourceType/$DocumentId" -Headers $Headers -Method Get | |
} catch { | |
Write-Error "StatusCode: $($_.Exception.Response.StatusCode.value__) | ExceptionMessage: $($_.Exception.Message) | $_" | |
} | |
} | |
function Remove-CosmosDocument { | |
<# | |
.SYNOPSIS | |
Remove a Cosmos DB NoSQL API document using the REST API. Uses Master Key Authentication. | |
.LINK | |
New-CFCosmosMasterKeyAuthorizationSignature | |
.EXAMPLE | |
$RemoveDocParams = @{ | |
Endpoint = 'https://xxxxx.documents.azure.com:443/' | |
MasterKey = $MasterKey | |
ResourceId = "dbs/$DatabaseId/colls/$CollectionId" | |
PartitionKeyValue = $PartitionKeyValue | |
DocumentId = $DocumentId | |
} | |
Remove-CosmosDocument @RemoveDocParams | |
#> | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory)] | |
[string] $Endpoint, | |
[Parameter(Mandatory)] | |
[string] $MasterKey, | |
[Parameter(Mandatory)] | |
[string] $ResourceId, | |
[Parameter()] | |
[string] $ResourceType = 'docs', | |
[Parameter(Mandatory)] | |
[string] $PartitionKeyValue, | |
[Parameter(Mandatory)] | |
[string] $DocumentId | |
) | |
# Calculate current date for use in Authorization header | |
$Date = [DateTime]::UtcNow.ToString('r') | |
# Compute Authorization header value and define headers dictionary | |
$AuthorizationKey = New-MasterKeyAuthorizationSignature -Method Delete -ResourceId "$ResourceId/$ResourceType/$DocumentId" -Date $Date -MasterKey $MasterKey | |
$Headers = @{ | |
'accept' = 'application/json' | |
'authorization' = $AuthorizationKey | |
'cache-control' = 'no-cache' | |
'content-type' = 'application/json' | |
'x-ms-date' = $Date | |
'x-ms-documentdb-partitionkey' = "[`"$PartitionKeyValue`"]" | |
'x-ms-version' = '2018-12-31' | |
} | |
# Send request to NoSQL REST API | |
try { | |
Invoke-RestMethod -Uri "$Endpoint$ResourceId/$ResourceType/$DocumentId" -Headers $Headers -Method Delete | |
} catch { | |
Write-Error "StatusCode: $($_.Exception.Response.StatusCode.value__) | ExceptionMessage: $($_.Exception.Message) | $_" | |
} | |
} | |
function Search-CosmosDocuments { | |
<# | |
.SYNOPSIS | |
Retrieve one or more Cosmos DB NoSQL API documents by query using the REST API. Uses Master Key Authentication. | |
.LINK | |
New-MasterKeyAuthorizationSignature | |
.EXAMPLE | |
$Query = @{ | |
query = 'SELECT * FROM c WHERE c[@PartitionKey] = @PartitionKeyValue' | |
parameters = @( | |
@{ | |
name = '@PartitionKey' | |
value = $PartitionKey | |
} | |
@{ | |
name = '@PartitionKeyValue' | |
value = $PartitionKeyValue | |
} | |
) | |
} | |
$QueryDocParams = @{ | |
Endpoint = 'https://xxxxx.documents.azure.com:443/' | |
MasterKey = $MasterKey | |
ResourceId = "dbs/$DatabaseId/colls/$CollectionId" | |
Query = $Query | |
} | |
Search-CosmosDocuments @QueryDocParams | |
#> | |
[CmdletBinding()] | |
param ( | |
[Parameter(Mandatory)] | |
[string] $Endpoint, | |
[Parameter(Mandatory)] | |
[string] $MasterKey, | |
[Parameter(Mandatory)] | |
[string] $ResourceId, | |
[Parameter()] | |
[string] $ResourceType = 'docs', | |
[Parameter(Mandatory)] | |
[psobject] $Query | |
) | |
# Calculate current date for use in Authorization header | |
$Date = [DateTime]::UtcNow.ToString('r') | |
# Compute Authorization header value and define headers dictionary | |
$AuthorizationKey = New-MasterKeyAuthorizationSignature -Method Post -ResourceId $ResourceId -Date $Date -MasterKey $MasterKey | |
$Headers = @{ | |
'accept' = 'application/json' | |
'authorization' = $AuthorizationKey | |
'cache-control' = 'no-cache' | |
'content-type' = 'application/query+json' | |
'x-ms-date' = $Date | |
'x-ms-documentdb-isquery' = 'True' | |
'x-ms-documentdb-query-enablecrosspartition' = 'True' | |
'x-ms-version' = '2018-12-31' | |
} | |
# Send request to NoSQL REST API | |
try { | |
Invoke-RestMethod -Uri "$Endpoint$ResourceId/$ResourceType" -Headers $Headers -Method Post -Body ($Query | ConvertTo-Json) | |
} catch { | |
Write-Error "StatusCode: $($_.Exception.Response.StatusCode.value__) | ExceptionMessage: $($_.Exception.Message) | $_" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment