5 Cosmos DB Users, Permissions, Partition Keys - adamhockemeyer/Azure-Functions---CosmosDB-ResourceToken-Broker GitHub Wiki

This page is here to help describe what is actually going on with the the actual user, and concepts inside Cosmos DB such as the User, Permission, and the Partition Keys.

Users and Permissions in Cosmos DB provide an extra layer of security in the account for your database and collections.

Cosmos DB Security Documentation

Users


SQL Server for example also has the notion of a Database User which can be granted access to certain things, and this is really no different in theory with Cosmos DB. A user is someone or something (i.e. service account) that can have access to some resource.

A user can be created in Cosmos DB and then we can create a permission (i.e. access to something) and grant the permission to the user.

The only thing we need to create a user in Cosmos DB is an id.

In our code in this repo, we are creating a user in Cosmos DB with the user_id value from using the built in 'Authentication\Authorization' on the Azure Function.

Permissions


Permissions in Cosmos DB have 4 primary properties:

  • PermissionMode
  • ResourceLink
  • ResourcePartitionKey
  • Id
permission = new Permission
                    {

                        PermissionMode = permissionMode,
                        ResourceLink = collection.SelfLink,
                        // Permission restricts access to this partition key
                        ResourcePartitionKey = new PartitionKey(userId),
                        // Unique per user
                        Id = permissionId   

                    };

PermissionMode You only have two options here, PermissionMode.Read or PermissionMode.All, and like you would expect, limits the scope of what you are able to do with the data.

ResourceLink ResourceLink is really the meat of what this permission is allowing the user to access. In Cosmos DB, many things are resources such as Database's, Collections, Documents, and Attachments. Depending on the granularity, multiple permissions can be created and assigned to a user based on the data they should be able to have access to.

ResourcePartitionKey ResourcePartitionKey provides an additional layer of security if this value is set, to restrict the permission to only be able to work with a specific partition of the resource. Our ResourceTokenBroker API uses the ResourcePartitionKey and sets this as the userid, to allow user to only work with their documents.

Example:

Based on the code in this tutorial, we are using just 1 collection called 'dataCollection'.

Inside of the collection can be documents of all sorts and each of these documents has a property that we called "PartitionKey" or "_pk" (see TypedDocument<T> in the Shared project).

If we then create a Dog document, and set the partition key to [email protected], then based on the permission that we created and that was returned to the user in form of a Resource Token, once this document is created, only [email protected] would be able to access this document. If there are other Dog documents in the collection, Sue will only receive back the documents where the partition key matches her user id, since we set the permission up this way.

Now, a backend service using the "master key", could access any of the data, no matter the permission. So you could have the user interact primarily with Cosmos DB directly with only access to their information, but then still have a few REST services (i.e. WebAPI) to serve up a few more resources that need broader access.

If we didn't set the ResourcePartitionKey on the permission to a partition key of the userid, then we would be granting the user access based on the PermissionMode (either Read only or Read/Write) to anything in the ResourceLink. If the ResourceLink points to a collection like in our example, the user would have access to anything in the entire collection. So the ResourcePartitionKey helps provide a finer layer of control over what the user has access to in the resource.

Partition Keys


First, a good resource about Partition Keys can be found on the official docs site.

Fixed size collections (10GB) don't require a partition key, in fact, the portal won't even allow you to specify one.

Unlimited size collections do require a partition key.

Partition keys play an important role in modeling your data to achieve the desired performance and scale that your application requires and that is available to you with Cosmos DB.

Partition Keys should be fairly unique so that high throughput and scale can be achieved. Keep in mind that all data with the same partition key can only grow to the max size of 10GB. You can use this to help you think of the right property to use as a partition key. Even if you pick the "Unlimited" collection size, each individual partition of data (think of this as a group of related data based on the partition key) can only be 10GB in size. Keep this in mind when deciding on a partition key.

Our example in this repo uses a generic partition key of "PartitionKey" or "_pk", so that we don't have to force a collection of documents to be based on one specific topic. For example, if we required that each document have a property with "UserId", then we are forcing our data model to have a "UserId" when its possible the piece of data has nothing to do with a "UserId".

Examples include "UserId" for user related information, "DeviceId" for IoT data, "ParcelNumber" for real estate, etc.

In the scenario of restricting user access to only their documents, it makes a lot of sense to set the partition key to the "UserId", and then grant the user a permission that gives them access to anything in the collection as long as the partition key matches their "UserId".

Resource Token


Resource Token is the core piece which this entire project and example are based off of.

By default, when you create a Cosmos DB account, you will get a "master key" and connection string. This "master key" is safe to use in a controlled environment such as with your own backend system. Cosmos DB provides a unique experience since it is a platform-as-a-service, that a client could call directly to Cosmos DB without the need for a mid-tier web service.

To facilitate the ability for a client to directly call Cosmos DB, a Resource Token can be created from creating a User and Permission in Cosmos DB.

A Resource Token is similar to the "master key" in that it use used to interact with the database, but the Resource Token is much more limited in scope, and will only give the client the ability to access the information that was originally granted from the permission that was created.