Managing Users & Permissions in Cosmos DB with PowerShell

If you’re just getting started with Cosmos DB, you might not have come across users and permissions in a Cosmos DB database. However, there are certain use cases where managing users and permissions are necessary. For example, if you’re wanting to be able to limit access to a particular resource (e.g. a collection, document, stored procedure) by user.

The most common usage scenario for users and permissions is if you’re implementing a Resource Token Broker type pattern, allowing client applications to directly access the Cosmos DB database.

Side note: The Cosmos DB implementation of users and permissions only provides authorization – it does not provide authentication. It would be up to your own implementation to manage the authentication. In most cases you’d use something like Azure Active Directory to provide an authentication layer.

But if you go hunting through the Azure Management Portal Cosmos DB data explorer (or Azure Storage Explorer) you won’t find any way to configure or even view users and permissions.

ss_cdb_cosmosdbdataexplorer

To manage users and permissions you need to use the Cosmos DB API directly or one of the SDKs.

But to make Cosmos DB users and permissions easier to manage from PowerShell, I created the Cosmos DB PowerShell module. This is an open source project hosted on GitHub. The Cosmos DB module allows you to manage much more than just users and permissions, but for this post I just wanted to start with these.

Requirements

This module works on PowerShell 5.x and PowerShell Core 6.0.0. It probably works on PowerShell 3 and 4, but I don’t have any more machines running this version to test on.

The Cosmos DB module does not have any dependencies, except if you call the New-Cosmos DbContext function with the ResourceGroup parameter specified as this will use the AzureRM PowerShell modules to read the Master Key for the connection directly from your Cosmos DB account. So I’d recommend installing the Azure PowerShell modules or if you’re using PowerShell 6.0, install the AzureRM.NetCore modules.

Installing the Module

The best way to install the Cosmos DB PowerShell module is from the PowerShell Gallery. To install it for only your user account execute this PowerShell command:

Install-Module -Name CosmosDB -Scope CurrentUser

ss_cdb_cosmosdbinstallmodulecurrentuser

Or to install it for all users on the machine (requires administrator permissions):

Install-Module -Name CosmosDB

ss_cdb_cosmosdbinstallmoduleallusers

Context Variable

Update 2018-03-06

As of Cosmos DB module v2.0.1, the connection parameter has been renamed to context and the New-CosmosDbConnection function has been renamed New-CosmosDbContext. This was to be more inline with naming adopted by the Azure PowerShell project. The old connection parameters and New-CosmosDbConnection function is still available as an alias, so older scripts won’t break. But these should be changed to use the new naming if possible as I plan to deprecate the connection version at some point in the future.

This post was updated to specify the new naming, but screenshots still show the Connection aliases.

Before you get down to the process of working with Cosmos DB resources, you’ll need to create a context variable containing the information required to connect. This requires the following information:

  1. The Cosmos DB Account name
  2. The Cosmos DB Database name
  3. The Master Key for the account (you can have the Cosmos DB PowerShell module get this directly from your Azure account if you wish).

To create the connection variable we just use the New-CosmosDbContext:

ss_cdb_cosmosdbnewconnection

If you do not wish to specify your master key, you can have the New-CosmosDbContext function pull your master key from the Azure Management Portal directly:

ss_cdb_cosmosdbnewconnectionviaportal

Note: This requires the AzureRM.Profile and AzureRM.Resoures module on Windows PowerShell 5.x or AzureRM.Profile.NetCore and AzureRM.Resources.NetCore on PoweShell Core 6.0.0.

Managing Users

To add a user to the Cosmos DB Database use the New-CosmosDBUser function:

New-CosmosDbUser -Context $context -Id 'daniel'

ss_cdb_cosmosdbnewuser

To get a list of users in the database:

Get-CosmosDbUser -Context $context

ss_cdb_cosmosdbgetusers

To get a specific user:

Get-CosmosDbUser -Context $context -Id 'daniel'

ss_cdb_cosmosdbgetuser

To remove a user (this will also remove all permissions assigned to the user):

Remove-CosmosDbUser -Context $context -Id 'daniel'

ss_cdb_cosmosdbremoveuser

Managing Permissions

Permissions in Cosmos DB are granted to a user for a specific resource. For example, you could grant a user access to just a single document, an entire collection or to a stored procedure.

To grant a permission you need to provide four pieces of information:

  1. The Id of the user to grant the permission to.
  2. An Id for the permission to create. This is just string to uniquely identify the permission.
  3. The permission mode to the permission: All or Read.
  4. The Id of the resource to grant access to. This can be generated from one of the Get-CosmosDb*ResourcePath functions in the CosmosDB PowerShell module.

In the following example, we’ll grant the user daniel all access to the TestCollection:

ss_cdb_cosmosdbnewpermission

Once a permission has been granted, you can use the Get-CosmosDbPermission function to retrieve the permission and with it the Resource Token that can be used to access the resource for a limited amount of time (between 10 minutes and 5 hours).

Note: as you have the Master Key already, using the Resource Token isn’t required.

For example, to retrieve all permissions for the user with Id daniel and a resource token expiration of 600 seconds:

Get-CosmosDbPermission -Context $context -UserId 'daniel' -TokenExpiry '600' |
fl *

ss_cdb_cosmosdbgetpermission

You can as expected delete a permission by using the Remove-CosmosDbPermission function:

Remove-CosmosDbPermission -Context $context -UserId 'daniel' -Id 'AccessTestCollection'

ss_cdb_cosmosdbremovepermission

Final Thoughts

So this is pretty much all there is to managing users and permissions using the Cosmos DB PowerShell module. This module can also be used to manage the following Cosmos DB resources:

  • Attachments
  • Collections
  • Databases
  • Documents
  • Offers
  • Stored procedures
  • Triggers
  • User Defined Functions

You can find additional documentation and examples of how to manage these resources over in the Cosmos DB PowerShell module readme file on GitHub.

Hopefully this will help you in any Cosmos DB automation tasks you might need to implement.

 

Advertisements

11 thoughts on “Managing Users & Permissions in Cosmos DB with PowerShell

    • Hi Frank! Great use case – I didn’t think about this use case, but it should be easy to support. This doesn’t work because internally the URI to the CosmosDB is built by combining the $account with the ‘.documents.azure.com’. However, there should be a simple work around you could use (until I add built in support): After creating the $connection variable, set the BaseUri property to ‘http://localhost:8081’. E.g. $connection.BaseUri = [uri] ‘http://localhost:8081’. I’m assuming here the emulator uses HTTP rather than HTTPS. What I’ll do is add a way to set the base URI through a parameter when creating the connection object.

      Like

      • Frank Monroe! says:

        Thanks! Gee I just spent an hour or so trying to figure it out looking at your code – which is great, I learned a lot about using PS for CosmosDB. If you can fix that would help me a lot.
        AFAIK that’s the best way to script a database?!?
        For SQL I had all mys database creaion scripts in SQL files and I ran a PS that ran all the SQLs in sequence, I was planning to do the same with your tool – do you know a better way (I mean for CosmosDB)?
        Thanks for the good work!

        Like

      • I’ll definitely fix this – I’ll get onto it over the weekend. Technically you could use anything that can hit a REST API to script the configuration of CosmosDB objects (Collections, Users, Permissions, Triggers, SP’s, UDF’s etc). But the goal of this module was mainly to make it a little bit easier if you’re not a Developer and are looking at this from a deployment side of things.

        I’ve used the exact same method as you’ve mentioned for SQL Server config as well, but as far as I’ve seen there isn’t anything similar in CosmosDB. That said, Microsoft moves extremely fast with this – so things could change in the near future. So essentially, my intent is to enable you to be able to fully script the config of a CosmosDB collection from code using this module.

        Liked by 1 person

    • Hi Orrin,

      I’m really glad you like it! I’ve actually got this on my backlog of features to add: https://github.com/PlagueHO/CosmosDB/issues/33

      I’ll make this a high priority to implement. I have actually prepared for this, but have’t implemented it. There is a keytype parameter on `New-CosmosDbContext` that allows values ‘master’ and ‘resource’. I just haven’t completed the feature (e.g. I don’t think it works – it might but pretty sure it doesn’t).

      E.g.
      $cosmosDbContext = New-CosmosDbContext -Account ‘MyAzureCosmosDB’ -Database ‘MyDatabase’ -Key $resourceKey -KeyType resource

      If you “watch” the repo on Github you’ll see when this gets released.

      Thanks
      dan

      Like

  1. Ryan says:

    How can I use a resource token to return documents that a user has access to? The collection level works fine but I can not get it to work at the document level, such as when a user is given access to a particular partition key.

    Like

    • Hi Ryan,

      That is a good question. You should be able to use the Get-CosmosDBCollection to cmdlet to return all permissions assigned to the user. You could then scan through the returned list and look at the resource path to identify all the Document type resources.

      E.g.
      $permissions = Get-CosmosDbPermission -Context $cosmosDB -UserId ‘MyUser’

      However, I wasn’t actually aware that you could assign a permission to a particular partition key – do you have a reference to this?

      Like

      • Ryan says:

        This was helpful. I was able to get it to work once I changed the Context to be at the “docs” level rather than the collection level.

        For permissions to a specific partition key, you specify the partition key as part of the permission object creation. Something like this with C# anyway:
        Permission projectPermission = new Permission
        {
        PermissionMode = PermissionMode.All,
        ResourceLink = collection.SelfLink,
        ResourcePartitionKey = new PartitionKey(userId),
        Id = “{userId}_{collection.Id}”
        };

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s