New-CDBAuthHeader.psm1
$FunctionScriptName = "New-CDBAuthHeader" Write-Verbose "Import-Start| [$($FunctionScriptName)]" #* Dependencies # N/A #todo: Support AAD based tokens - https://docs.microsoft.com/en-us/rest/api/cosmos-db/access-control-on-cosmosdb-resources #todo: support scoped/resource based tokens function New-CDBAuthHeader { <# .SYNOPSIS Creates an auth Header for CosmosDB SQL API via REST .DESCRIPTION Creates an auth Header for CosmosDB SQL API via REST Used by SQL/Core REST API .PARAMETER Config Config array Accepts the following values: DatabaseID / CollectionID / AuthKey / keyType / CosmosDBEndpoint / KeyType All required values can be set directly. Directly set values have precedent. Not all values may be required. .PARAMETER DatabaseID Can be set via -Config value Name of the CosmosDB Database .PARAMETER CollectionId Can be set via -Config value Name of the CosmosDB Collection .PARAMETER AuthKey Can be set via -Config value Key value to authenticate against cosmosDB .PARAMETER KeyType Can be set via -Config value Type of AuthKey provided. Default value: "master" .PARAMETER PartitionKey Value of the Partition. Not the Name of the Key itself! .PARAMETER DocumentID ID of the document Value of the document value "id" .PARAMETER HTTPverb HTTPverb used by REST API Use as required: GET = Query document POST = Write document PATCH = Patch part of document DELETE = Delete document .PARAMETER DocumentUpsert Only for HTTPverb: POST - Default: TRUE Sets the "x-ms-documentdb-is-upsert" header True = Overwrites existing document if exists. Create if new. False = Throws error if document exists. Create if new. .PARAMETER enablecrosspartition Only for HTTPverb: POST - Default: FALSE Sets the "x-ms-documentdb-query-enablecrosspartition" header True = Scopes multiple partitions. The primary one still needs to be defined. False = Only uses the defined partition. Increases the performance. .PARAMETER APIVersion API Version of the CosmosDB REST API Default value: "2018-12-31" .PARAMETER AuthSignatureOnly Default value: FALSE TRUE = Returns only the signature without a complete header. False = Returns the usable auth header. .EXAMPLE New-CDBAuthHeader -Config $Config -PartitionKey $PKEY -HTTPverb "POST" New-CDBAuthHeader -Config $Config -PartitionKey $PKEY -HTTPverb "GET" -DocumentID $DocumentID .NOTES AUTHOR: Ken Dobrunz // Ken.Dobrunz@Skaylink.com LASTEDIT: 05.08.2022 - Version: 1.0 #> [cmdletbinding()] Param( #* Active data # Config or direct values needed [Parameter()]$Config, [Parameter()][string]$DatabaseID, [Parameter()][string]$CollectionId, [Parameter()][string]$AuthKey, [Parameter()][string]$KeyType = "master", # Entity [parameter()][Alias('pkey')][string]$PartitionKey, [parameter()][Alias('verb')][string]$HTTPverb, #? GET / POST / DELETE / PATCH # GET Variables [Parameter()][Alias('doc')][string]$DocumentID, # POST Variables [parameter()][Alias('upsert')][bool]$DocumentUpsert = $true, [parameter()][bool]$enablecrosspartition = $false, # Tech Config [parameter()][string]$APIVersion = "2018-12-31", [parameter()][bool]$AuthSignatureOnly = $false ) Begin { $SelfIdentifier = "New-CDBAuthHeader" # Variables for future use (Scoping) $resourceType = "docs" $tokenVersion = "1.0" # Check Config / Set Variables $DatabaseID = if ($DatabaseID) { $DatabaseID }elseif ($Config.DatabaseID) { $Config.DatabaseID }else { Write-Error "[$($SelfIdentifier)] No DatabaseID provided" } $CollectionId = if ($CollectionId) { $CollectionId }elseif ($Config.CollectionId) { $Config.CollectionId }else { Write-Error "[$($SelfIdentifier)] No CollectionId provided" } $AuthKey = if ($AuthKey) { $AuthKey }elseif ($Config.AuthKey) { $Config.AuthKey }else { Write-Error "[$($SelfIdentifier)] No AuthKey provided" } $KeyType = if ($KeyType) { $KeyType }elseif ($Config.KeyType) { $Config.KeyType }else { Write-Error "[$($SelfIdentifier)] No KeyType provided" } switch ($HTTPverb) { "GET" { $DocumentID = if ($DocumentID) { $DocumentID }elseif ($Config.DocumentID) { $Config.DocumentID }else { Write-Error "[$($SelfIdentifier)] No DocumentID provided" } $ResourceLink = "dbs/$DatabaseId/colls/$CollectionId/$resourceType/$DocumentID" } "DELETE" { $DocumentID = if ($DocumentID) { $DocumentID }elseif ($Config.DocumentID) { $Config.DocumentID }else { Write-Error "[$($SelfIdentifier)] No DocumentID provided" } $ResourceLink = "dbs/$DatabaseId/colls/$CollectionId/$resourceType/$DocumentID" } "PATCH" { $DocumentID = if ($DocumentID) { $DocumentID }elseif ($Config.DocumentID) { $Config.DocumentID }else { Write-Error "[$($SelfIdentifier)] No DocumentID provided" } $ResourceLink = "dbs/$DatabaseId/colls/$CollectionId/$resourceType/$DocumentID" } "POST" { $ResourceLink = "dbs/$DatabaseId/colls/$CollectionId" } Default { Write-Error "[$($SelfIdentifier)] Invalid or no HTTPVERB provided: [$($HTTPverb)]" } } } Process { $dateTime = [DateTime]::UtcNow.ToString("r") #? Format as required by CDB Write-Debug "[$($SelfIdentifier)] Creating [$($keyType)] signature for [$($HTTPverb)][$($ResourceLink)] on [$($dateTime)]" # Generate Signature $hmacSha256 = New-Object System.Security.Cryptography.HMACSHA256 $hmacSha256.Key = [System.Convert]::FromBase64String($AuthKey) $payLoad = "$($HTTPverb.ToLowerInvariant())`n$($resourceType.ToLowerInvariant())`n$resourceLink`n$($dateTime.ToLowerInvariant())`n`n" $hashPayLoad = $hmacSha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($payLoad)) $signature = [System.Convert]::ToBase64String($hashPayLoad); $authsignature = [System.Web.HttpUtility]::UrlEncode("type=$keyType&ver=$tokenVersion&sig=$signature") if (!$AuthSignatureOnly) { # Creating header $header = @{ "Authorization" = $authsignature "x-ms-documentdb-partitionkey" = '["' + $PartitionKey + '"]' "x-ms-version" = $APIVersion "x-ms-date" = $dateTime "Accept" = "application/json" } # Adding optional values if ($HTTPverb = "POST") { if ($enablecrosspartition) { $header."x-ms-documentdb-query-enablecrosspartition" = $true } if ($DocumentUpsert) { $header."x-ms-documentdb-is-upsert" = $true } } } } End { if ($AuthSignatureOnly) { Write-Debug "[$($SelfIdentifier)] Returing Auth Signature" return $authsignature } else { Write-Debug "[$($SelfIdentifier)] Returing Auth Header" return $header } } } #v0.1 Export-ModuleMember -Function * Write-Verbose "Import-END| [$($FunctionScriptName)]" |