Learn how to perform core administrative tasks on the Azure Cosmos DB using Azure PowerShell.
Latest posts by Timothy Warner (see all)

Whereas Azure SQL Database is Microsoft Azure's primary relational database management system, Cosmos DB is Azure's main nonrelational database offering. Cosmos DB offers cloud development teams several significant advantages, including:

  • Fully managed Platform as a Service architecture
  • Five APIs/data models to support migration from various NoSQL databases
  • Five transaction consistency levels
  • Turnkey global replication
  • Multi-region read/write access

Cosmos DB is a very cool product, for sure. But what does this opinion have to do with the life of the busy Windows systems administrator? Well, potentially a lot, especially for businesses adopting a "cloud-first" application development/deployment model in Azure.

Azure Cosmo DB logo

Azure Cosmo DB logo

Let's start this lesson by deploying a Cosmos DB account using Azure PowerShell. Next, I'll show you a couple of administrative actions we can automate. Access key regeneration is by far the most important, especially given recent tech news. Onward!

Sorting our prerequisites

To perform the steps I'll demonstrate, you'll need some tools. Here's the short list:

Open an elevated PowerShell console, and run the following statements to install Azure PowerShell:

Install-Module -Name Az -Force -Verbose
Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi; Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'; rm .\AzureCLI.msi

Installing Bicep CLI on Windows is a bit of a pain to do with PowerShell at this time. Thus, I suggest that you simply run the .MSI installer and be done with it.

Next, sign into Azure, and set your subscription context if necessary:

Connect-AzAccount
Set-AzContext -SubscriptionName "My Azure Subscription"

Deploying a Cosmos DB account

Start your Cosmos DB journey by creating a Cosmos account. The account is associated with one and only one of the supported APIs:

  • Core: This is the preferred API because it's where Microsoft does all its innovation and new feature development. Data is stored as JSON documents, and the API uses a SQL-like query language.
  • MongoDB: Supports migration from MongoDB JSON databases.
  • Cassandra: Supports migration from Apache Cassandra wide column store databases.
  • Table: Supports migration from the Azure Table Storage service (part of the general purpose storage account).
  • Gremlin: Supports migration from Apache Gremlin graph databases.

We'll use Bicep to deploy the account. Note that your Cosmos DB account name needs to be globally unique. Here's the .bicep template:

param appName string = uniqueString(resourceGroup().id)
param accountName string = toLower('cosmos-${appName}')
param location string = resourceGroup().location
param databaseName string = toLower('db-${appName}')

resource cosmos 'Microsoft.DocumentDB/databaseAccounts@2020-04-01' = {
  name: accountName
  location: location
  properties: {
    enableFreeTier: true
    databaseAccountOfferType: 'Standard'
    consistencyPolicy: {
      defaultConsistencyLevel: 'Session'
    }
    locations: [
      {
        locationName: location
      }
    ]
  }
}

resource cosmosdb 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2020-04-01' = {
  name: '${cosmos.name}/${databaseName}'
  properties: {
    resource: {
      id: databaseName
    }
    options: {
      throughput: 400
    }
  }
}

To perform the deployment using Azure PowerShell, run the command below. Note that the resource group you specify must already exist:

New-AzResourceGroupDeployment -Name cosmos-db -ResourceGroupName "your-rg" -TemplateFile "./cosmos-account.bicep" -Verbose

At the end of this process, you'll have a new Cosmos DB account that uses the Core (SQL) API. You'll also have a new, empty database.

In the Core Cosmos DB resource model, the database comprises one or more containers, which in turn contain your JSON documents. We'll do that next.

Creating a Cosmos DB container and inserting data

Now, we tap into the Az.CosmosDB PowerShell module where all the programmatic Cosmos DB goodness is found. Let's create a new container to store JSON data. It's beyond our scope, but you can check the docs to learn more about selecting the best partition key, indexing, and Request Unit (RU) scale settings:

# Create an Azure Cosmos DB container with default indexes and throughput at 400 RU (Code reference: https://timw.info/7mo)
$resourceGroupName = "myResourceGroup"
$accountName = "mycosmosaccount"
$databaseName = "myDatabase"
$containerName = "myContainer"
$partitionKeyPath = "/myPartitionKey"
$throughput = 400 #minimum = 400

New-AzCosmosDBSqlContainer `
    -ResourceGroupName $resourceGroupName `
    -AccountName $accountName `
    -DatabaseName $databaseName `
    -Name $containerName `
    -PartitionKeyKind Hash `
    -PartitionKeyPath $partitionKeyPath `
    -Throughput $throughput

To insert data into the container, we'll need to fetch the CosmosDB community module from the PowerShell Gallery:

Install-Module -Name CosmosDB -Verbose
Import-Module -Name CosmosDB

We can then invoke the module's New-CosmosDbDocument command to insert a new JSON document into the container:

# Insert data into the container (Ref: https://timw.info/put)
$cosmosDbContext = New-CosmosDbContext -Account $accountName -Database $databaseName -ResourceGroup $resourceGroupName

$document = @"
{
        "id": "7ea9b3c6-bb1a-3c38-2268-8e17de5b1c70",
        "productName": "widget-211",
        "key": "211"
    }

"@

New-CosmosDbDocument -Context $cosmosDbContext -CollectionId 'myContainer' -DocumentBody $document -PartitionKey "211"

Querying the Cosmos DB container

We can continue to use PowerShell and the Cosmos DB module to run queries against our container and JSON data. This first example assumes you know your document's ID:

PS C:\> Get-CosmosDbDocument -Context $cosmosDbContext -CollectionId "myContainer" -Id "7ea9b3c6-bb1a-3c38-2268-8e17de5b1c70",

The second example implements the Core API's SQL-like query language:

$query = "SELECT * FROM myContainer c WHERE (c.productName = 'widget-211')"
Get-CosmosDbDocument -Context $cosmosDbContext -CollectionId 'myContainer' -Query $query

Regenerating Cosmos DB account access keys

Last but certainly not least, I want to teach you how to programmatically regenerate your Cosmos DB account's primary read/write access key. Why? Because the Microsoft Security Response Center disclosed an enormous breach recently in which millions of Cosmos DB customers' databases were exposed to the public!

The vulnerability in question affected only the account's primary read/write key. However, you can also perform this procedure on the secondary read/write and primary and secondary read-only keys. The following commands come from the native Az.CosmosDB modules, by the way:

Subscribe to 4sysops newsletter!

# See current primary rw key value for reference
(Get-AzCosmosDBAccountKey -ResourceGroupName $resourceGroupName -Name $accountName).PrimaryMasterKey
# Regenerate Cosmos account's primary read/write key
New-AzCosmosDBAccountKey -ResourceGroupName $resourceGroupName -Name $accountName -KeyKind "primary"

I suggest you define an Azure Automation runbook and schedule Cosmo DB account key regeneration on a regular basis.

avatar
0 Comments

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account