Azure-sdk-for-java: [BUG] - ChangeFeedProcessor is not able to work with Resource Token authentication

Created on 17 Dec 2020  路  5Comments  路  Source: Azure/azure-sdk-for-java

Describe the bug
ChangeFeedProcessor is not able to work with Resource Token authentication because during the startup it needs a permission at database level due to a readDatabase operation.

To Reproduce
It's enough to use CosmosClient that uses TokenResolver instead of MasterKey

Code Snippet
The version used is azure-cosmos 3.7.5
Class: com.azure.data.cosmos.internal.changefeed.implementation.ChangeFeedProcessorBuilderImpl
Method: private Mono initializeCollectionPropertiesForBuild()

private Mono<ChangeFeedProcessor> initializeCollectionPropertiesForBuild() {
        if (this.changeFeedProcessorOptions == null) {
            this.changeFeedProcessorOptions = new ChangeFeedProcessorOptions();
        }
        return this.feedContextClient
            .readDatabase(this.feedContextClient.getDatabaseClient(), null)
            .map( databaseResourceResponse -> {
                this.databaseResourceId = databaseResourceResponse.database().id();
                return this.databaseResourceId;
            })
            .flatMap( id -> this.feedContextClient
                .readContainer(this.feedContextClient.getContainerClient(), null)
                .map(documentCollectionResourceResponse -> {
                    this.collectionResourceId = documentCollectionResourceResponse.container().id();
                    return this;
                }));
    }

Expected behavior
This readDatabase retrieves only the database name, so it could avoid reading database information.

Additional context
The issue can be resolved using this code:

private Mono<ChangeFeedProcessor> initializeCollectionPropertiesForBuild() {
    if (this.changeFeedProcessorOptions == null) {
      this.changeFeedProcessorOptions = new ChangeFeedProcessorOptions();
    }

    return Mono.just(this.feedContextClient.getDatabaseClient().id())
        .flatMap(id -> this.feedContextClient
            .readContainer(this.feedContextClient.getContainerClient(), null)
            .map(documentCollectionResourceResponse -> {
              this.collectionResourceId = documentCollectionResourceResponse.container().id();
              return this;
            }));
  }
customer-reported needs-triage question

Most helpful comment

@kushagraThapar, We (@apescione and me) are totally aware that by using the latest SDK plus the masterkey everything works fine, but for security reasons, we cannot use the masterkey in production environments. This means that we will not use the v4 driver till the AAD token based implementation will become GA.

Please consider also that v4 SDK has changed the interfaces about Resource Token like TokenResolver so it is not backward compatible with the v3. This makes the adoption of the newer SDK more difficult.

@milismsft, Does it mean that the solution provided is not useful? of course, the assumption is that the resource token needs to be refreshed once it has expired

All 5 comments

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @kushagraThapar, @anfeldma-ms

@apescione Can you please try the latest version of azure-cosmos - https://mvnrepository.com/artifact/com.azure/azure-cosmos/4.10.0
We strongly recommend all users to use the version v4 of Java Cosmos SDK.
@milismsft - please take a look at this in case the issue does not get resolved on latest version of V4.

ChangeFeedProcessor is simply not design to work with a resource token unless the work expected to be executed finishes before the resource token is to expire. The current implementation follows a "push" model, which means that periodically the CFP instance will reach out to Cosmos and look for any new feeds/document changes. This process is design to run continuously, longer than the resource token expiry time.
An AAD token based implementation will definitely address this limitation, combining select permissions and scopes within one model. Currently this feature is in "preview" and expected to GA sometime this spring. It is definitely worth checking it out.

Also regarding readDatabase(), in V4 version of the Cosmos SDK cosmosClient.getDatabase(dbID) will not make a network call and a resource token can be used in such cases. Depending on how the resource token was configured, any service request must be within the scope of the collection for which the token was acquired.

@kushagraThapar, We (@apescione and me) are totally aware that by using the latest SDK plus the masterkey everything works fine, but for security reasons, we cannot use the masterkey in production environments. This means that we will not use the v4 driver till the AAD token based implementation will become GA.

Please consider also that v4 SDK has changed the interfaces about Resource Token like TokenResolver so it is not backward compatible with the v3. This makes the adoption of the newer SDK more difficult.

@milismsft, Does it mean that the solution provided is not useful? of course, the assumption is that the resource token needs to be refreshed once it has expired

Was this page helpful?
0 / 5 - 0 ratings