Skip to content

Commit

Permalink
BREAKING CHANGE: Add Support for RBAC using Entra ID Token via New-Co…
Browse files Browse the repository at this point in the history
…smosDbContext - Fixes #479 (#483)
  • Loading branch information
PlagueHO authored May 19, 2024
1 parent 740b9ec commit a83196e
Show file tree
Hide file tree
Showing 28 changed files with 2,457 additions and 574 deletions.
33 changes: 31 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed MacOS-10.15 testing from build pipeline because it is no longer supported by Microsoft
managed Azure DevOps images - Fixes [Issue #476](https://github.com/PlagueHO/CosmosDB/issues/476).
- Added macOS-12 testing to build pipeline - Fixes [Issue #477](https://github.com/PlagueHO/CosmosDB/issues/477).
- Changed integration tests to deploy Cosmos DB using Bicep.
- Update `requirements.psd1` to install modules `Az.Accounts` 2.19.0 and `Az.Resources` 6.16.2.
- Renamed `New-CosmosDbAuthorizationToken` to `New-CosmosDbAuthorizationHeader` to better indicate
actual function return type.
- Refactored `Invoke-CosmosDbRequest` to support getting the EntraIdToken property from the context object
and using it for authentication if it is provided. If the Key property is provided, the EntraIdToken property
will take precendence and the key will be ignored.
- Updated CI pipeline to use `PublishCodeCoverageResults@2` task rather than `PublishCodeCoverageResults@1`
task to support the latest version of the task.

### Changed

- BREAKING CHANGE: Updated module to require `Az.Accounts` v2.19.0 or newer and `Az.Resources`
v6.16.2 or newer.
- Renamed `New-CosmosDbAuthorizationHeader` to `Get-CosmosDbAuthorizationHeaderFromContext` to better indicate
actual function behaviour.
- Renamed `Get-CosmosDbAuthorizationHeadersFromContext` to `Get-CosmosDbAuthorizationHeaderFromContextResourceToken` to better
indicate actual function behaviour and align naming convention.
- Refactored `Invoke-CosmosDbRequest` to clean up logic to generate the authorization header.
- Added new utillity function `Get-CosmosDbAuthorizationHeaderFromContextEntraId` to generate the authorization
header when an Entra ID Token is provided in the context. This function is used by `Invoke-CosmosDbRequest` to
generate the authorization header when an Entra ID Token is provided.

### Added

- Added support for setting an Entra Id OAuth2 Token in the `New-CosmosDbContext` - Fixes [Issue #479](https://github.com/PlagueHO/CosmosDB/issues/479).
- Added new `Get-CosmosDbEntraIdToken` function that uses `Get-AzAccessToken` to get an Entra Id Token
for use in Cosmos DB requests. This is used by `New-CosmosDbContext` to set the Entra Id Token in the
context object - Fixes [Issue #479](https://github.com/PlagueHO/CosmosDB/issues/479).

## [4.7.0] - 2023-01-29

Expand Down Expand Up @@ -666,7 +695,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [2.0.8.350] - 2018-04-05

- Fixed `New-CosmosDbAuthorizationToken` function to support
- Fixed `New-CosmosDbAuthorizationHeader` function to support
generating authorization tokens for case sensitive resource
names - See [Issue #76](https://github.com/PlagueHO/CosmosDB/issues/76).
Thanks [MWL88](https://github.com/MWL88).
Expand Down Expand Up @@ -775,7 +804,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Fixed bug in `New-CosmosDbConnection` connecting to Azure and
improved tests.
- Changed `New-CosmosDbAuthorizationToken` to replaced `Connection`
- Changed `New-CosmosDbAuthorizationHeader` to replaced `Connection`
parameter with `Key` and `KeyType` parameter.
- Fixed bug in `Invoke-CosmosDbRequest` that can cause connection
object to be changed.
Expand Down
172 changes: 139 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@
- [Installation](#installation)
- [Getting Started](#getting-started)
- [Working with Contexts](#working-with-contexts)
- [Create a Context using an Entra ID Authorization Token](create-a-context-using-an-entra-id-authorization-token)
- [Configuring Role-Based Access Control (RBAC) with Entra ID](#configuring-role-based-access-control-rbac-with-entra-id)
- [Database Operations allowed by Role-Based Access Control](#database-operations-allowed-by-role-based-access-control)
- [Create a Context specifying the Key Manually](#create-a-context-specifying-the-key-manually)
- [Use CosmosDB Module to Retrieve Key from Azure Management Portal](#use-cosmosdb-module-to-retrieve-key-from-azure-management-portal)
- [Create a Context from Resource Authorization Tokens](#create-a-context-from-resource-authorization-tokens)
- [Create a Context for a Cosmos DB in Azure US Government Cloud](#create-a-context-for-a-cosmos-db-in-azure-us-government-cloud)
- [Create a Context for a Cosmos DB in Azure China Cloud (Mooncake)](#create-a-context-for-a-cosmos-db-in-azure-china-cloud-mooncake)
- [Create a Context for a Cosmos DB with a Custom Endpoint](#create-a-context-for-a-cosmos-db-with-a-custom-endpoint)
- [Use CosmosDB Module to Retrieve Key from Azure Management Portal](#use-cosmosdb-module-to-retrieve-key-from-azure-management-portal)
- [Create a Context for a Cosmos DB Emulator](#create-a-context-for-a-cosmos-db-emulator)
- [Create a Context from Resource Authorization Tokens](#create-a-context-from-resource-authorization-tokens)
- [Working with Accounts](#working-with-accounts)
- [Working with Databases](#working-with-databases)
- [Working with Offers](#working-with-offers)
Expand Down Expand Up @@ -81,16 +84,15 @@ For more information on the Cosmos DB Rest APIs, see [this link](https://docs.mi

This module requires the following:

- Windows PowerShell 5.x or PowerShell 6.x:
- **Az.Profile** and **Az.Resources** PowerShell modules
are required if using `New-CosmosDbContext -ResourceGroupName $resourceGroup`
or `*-CosmosDbAccount` functions.
- Windows PowerShell 5.x, PowerShell Core 6.x or PowerShell 7.x

### PowerShell Module Dependencies

> Note: As of 3.0.0.0 of the CosmosDB module, support for **AzureRm** and
> **AzureRm.NetCore** PowerShell modules has been deprecated due to being
> superceeded by the **Az** modules. If it is a requirement that **AzureRm**
> or **AzureRm.NetCore** modules are used then you will need to remain on
> CosmosDB module 2.x.
- **Az.Account**: v2.19.0 or newer.
- **Az.Resources**: 6.16.2 or newer.

These modules are required if using `New-CosmosDbContext -ResourceGroupName $resourceGroup`
or `*-CosmosDbAccount` functions.

## Recommended Knowledge

Expand Down Expand Up @@ -129,8 +131,95 @@ the Azure management portal for you.

### Working with Contexts

#### Create a Context Using an Entra ID Authorization Token

You can create a context object that can include use an _Entra ID Authorization Token_
that will be used to authenticate requests to Cosmos DB.

> Important: This is a recommended security practice to use when you've
> [configured role-based access control with Microsoft Entra ID](https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-rbac)
> on your Azure Cosmos DB account. It will help you keep your account secure
> by not exposing the primary or secondary keys in your code.
To create a context object using an _Entra ID Authorization Token_ you will need
to set the `EntraIdToken` parameter to the token you have retrieved from Entra ID
for the identity that you have given appropriate permissions to the `account`,
`database` and/or `collection`. See [this page](https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-rbac#concepts) for more infomration.

```powershell
# Get an OAuth2 resource token from Entra ID for the Cosmos DB account.
# This will use the currently logged in user to authenticate to Entra ID to
# get the token. There are many other ways of doing this.
$entraIdOAuthToken = Get-CosmosDbEntraIdToken -Endpoint 'https://MyAzureCosmosDB.documents.azure.com'
$newCosmosDbContextParams = @{
Account = 'MyAzureCosmosDB'
EntraIdToken = $entraIdOAuthToken
}
$accountContext = New-CosmosDbContext @newCosmosDbContextParams
Get-CosmosDbCollection -Context $accountContext -Id MyNewCollection
```

An alternate method is to allow the New-CosmosDbContext cmdlet to retrieve the
Entra ID token for you. This will require you to have already logged into Azure
and will use the base URI detected for the account as the resource URI for the
token request.

```powershell
$newCosmosDbContextParams = @{
Account = 'MyAzureCosmosDB'
AutoGenerateEntraIdToken = $true
}
$accountContext = New-CosmosDbContext @newCosmosDbContextParams
Get-CosmosDbCollection -Context $accountContext -Id MyNewCollection
```

> Important: Using an Entra ID Authorization Token is only supported by setting it
> in a CosmosDB.Context object and passing that to the commands you want to execute.
> Not all commands support this method of authentication. If you need to use a command
> that doesn't support this method of authentication, you will need to use one of the
> other methods of authentication. See the [Database Operations allowed by Role-Based Access Control](#database-operations-allowed-by-role-based-access-control)
> section for more information.
##### Configuring Role-Based Access Control (RBAC) with Entra ID

There are several ways to configure a Cosmos DB Account with Role-Based Access Control,
including:

- *Azure Bicep*: An example can be found in the [\tests\TestHelper\AzureDeploy\CosmosDb.bicep](\tests\TestHelper\AzureDeploy\CosmosDb.bicep) file.
- *Azure PowerShell*: The integration tests use this method.
- *AzCli*.

> Important Note: One thing I found when adding a SQL Role Assignment to the Cosmos DB
> Account (or Database or Container) is that the principal ID must be the Object ID of
> the user, group or service principal that you want to assign the role to. You can't use
> the Application ID for this value.
For more information on how to configure Role-Based Access Control with Entra ID, see the
[Configure role-based access control with Microsoft Entra ID for your Azure Cosmos DB account](https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-rbac)
page.

##### Database Operations allowed by Role-Based Access Control

Only a subset of all the operations that can be performed on a Cosmos DB account are
allowed by Role-Based Access Control. The following operations are allowed:
This permission model covers only database operations that involve reading and writing data. It does not cover any kind of management operations on management resources, including:

- Create/Replace/Delete Database
- Create/Replace/Delete Container
- Read/Replace Container Throughput
- Create/Replace/Delete/Read Stored Procedures
- Create/Replace/Delete/Read Triggers
- Create/Replace/Delete/Read User Defined Functions

For more information on this, please see the [Role-based access control (RBAC) with Azure Cosmos DB](https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-rbac#permission-model) page.

#### Create a Context specifying the Key Manually

> Note: This method of authenticating to Cosmos DB is not recommended for
> production use. It is recommended to use the _Entra ID Authorization Token_
> method described above.
First convert your key into a secure string:

```powershell
Expand All @@ -144,8 +233,43 @@ create a context variable:
$cosmosDbContext = New-CosmosDbContext -Account MyAzureCosmosDB -Database MyDatabase -Key $primaryKey
```

#### Use CosmosDB Module to Retrieve Key from Azure Management Portal

> Note: This method of authenticating to Cosmos DB is not recommended for
> production use. It is recommended to use the _Entra ID Authorization Token_
> method described above.
To create a context object so that the _CosmosDB PowerShell module_
retrieves the primary or secondary key from the Azure Management
Portal, use the following command:

```powershell
$cosmosDbContext = New-CosmosDbContext -Account MyAzureCosmosDB -Database MyDatabase -ResourceGroupName MyCosmosDbResourceGroup -MasterKeyType SecondaryMasterKey
```

_Note: if PowerShell is not connected to Azure then an interactive
Azure login will be initiated. If PowerShell is already connected to
an account that doesn't contain the Cosmos DB you wish to connect to then
you will first need to connect to the correct account using the
`Connect-AzAccount` cmdlet._

#### Create a Context from Resource Authorization Tokens

> Note: This method of authenticating to Cosmos DB is better than using master key
> authentication, as it provides the ability to limit access to specific resources.
> However, it is recommended to use the _Entra ID Authorization Token_ method
> described above if possible.
See the section [Using Resource Authorization Tokens](#using-resource-authorization-tokens)
for instructions on how to create a Context object containing one or more _Resource
Authorization Tokens_.

#### Create a Context for a Cosmos DB in Azure US Government Cloud

> Note: This method of authenticating to Cosmos DB is not recommended for
> production use. It is recommended to use the _Entra ID Authorization Token_
> method described above.
Use the key secure string, Azure Cosmos DB account name and database to
create a context variable and set the `Environment` parameter to
`AzureUSGovernment`:
Expand All @@ -156,6 +280,10 @@ $cosmosDbContext = New-CosmosDbContext -Account MyAzureCosmosDB -Database MyData

#### Create a Context for a Cosmos DB in Azure China Cloud (Mooncake)

> Note: This method of authenticating to Cosmos DB is not recommended for
> production use. It is recommended to use the _Entra ID Authorization Token_
> method described above.
Use the key secure string, Azure Cosmos DB account name and database to
create a context variable and set the `Environment` parameter to
`AzureChinaCloud`:
Expand All @@ -173,22 +301,6 @@ Cosmos DB custom endpoint hostname:
$cosmosDbContext = New-CosmosDbContext -Account MyAzureCosmosDB -Database MyDatabase -Key $primaryKey -EndpointHostname documents.eassov.com
```

#### Use CosmosDB Module to Retrieve Key from Azure Management Portal

To create a context object so that the _CosmosDB PowerShell module_
retrieves the primary or secondary key from the Azure Management
Portal, use the following command:

```powershell
$cosmosDbContext = New-CosmosDbContext -Account MyAzureCosmosDB -Database MyDatabase -ResourceGroupName MyCosmosDbResourceGroup -MasterKeyType SecondaryMasterKey
```

_Note: if PowerShell is not connected to Azure then an interactive
Azure login will be initiated. If PowerShell is already connected to
an account that doesn't contain the Cosmos DB you wish to connect to then
you will first need to connect to the correct account using the
`Connect-AzAccount` cmdlet._

#### Create a Context for a Cosmos DB Emulator

Microsoft provides a [Cosmos DB emulator](https://docs.microsoft.com/azure/cosmos-db/local-emulator) that
Expand All @@ -208,12 +320,6 @@ $primaryKey = ConvertTo-SecureString -String 'GFJqJesi2Rq910E0G7P4WoZkzowzbj23Sm
$cosmosDbContext = New-CosmosDbContext -Emulator -Database MyDatabase -Uri https://cosmosdbemulator.contoso.com:9081 -Key $primaryKey
```

#### Create a Context from Resource Authorization Tokens

See the section [Using Resource Authorization Tokens](#using-resource-authorization-tokens)
for instructions on how to create a Context object containing one or more _Resource
Authorization Tokens_.

### Working with Accounts

You can create, retrieve, update and remove Azure Cosmos DB accounts using
Expand Down
5 changes: 3 additions & 2 deletions RequiredModules.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
Sampler = 'latest'
'Sampler.GitHubTasks' = 'latest'
MarkdownLinkCheck = 'latest'
'Az.Accounts' = '2.2.8'
'Az.Resources' = '1.3.1'
'Az.Accounts' = '2.19.0'
'Az.Resources' = '6.16.2'
'Az.CosmosDB' = '1.14.2' # Required by integration tests
}
Loading

0 comments on commit a83196e

Please sign in to comment.