Search code examples
c#azure-functionsazure-cosmosdbazure-keyvaultpolly

Polly Policy for azure cosmos function when cosmos Authkey updated


I am using an azure cosmos function, which has some azure auth Key in the key vault. The Authkey will be changed every 10 days. Whenever the auth key changed, I had to restart my function as I was receiving an error saying

"Unauthorized (401),The input authorization token can't serve the request. The wrong key is being used or the expected payload is not built as per the protocol".

My senior collague suggested using the Polly policy to resolve this without restarting the function.

Could someone please help me to resolve this? I am not understanding where to apply the Polly policy code exactly.

My ServiceCollectionExtenstion class a below (where I will receive the error)

public static IServiceCollection AddCosmosStore<TEntity>(this IServiceCollection services,
    string databaseName, Uri endpointUri, string authKey, Action<CosmosStoreSettings> settingsAction = null,
    string overriddenContainerName = "") where TEntity : class
{
    var settings = new CosmosStoreSettings(databaseName, endpointUri, authKey);
    settingsAction?.Invoke(settings);
    return services.AddCosmosStore<TEntity>(settings, overriddenContainerName);
}

public static IServiceCollection AddCosmosStore<TEntity>(this IServiceCollection services, CosmosStoreSettings settings, string overriddenContainerName = "") where TEntity : class
{
    services.AddSingleton<ICosmosStore<TEntity>>(x => new CosmosStore<TEntity>(settings, overriddenContainerName)); // error comes from here
    return services;
}

Error message as below

This can be resolved if I restart the function, but want to make it happen automatically

Thanks.


Solution

  • You can define a retry policy like this:

    var refreshAuthKeyPolicy = Policy
        .Handle<CosmosException>(ex => ex.StatusCode == (HttpStatusCode)401)
        .Retry(1, (response, retryCount) =>
        {
            //refresh authKey
            settings.AuthKey = newAuthKey;
        }
    );
    
    • .Handle<CosmosException>(ex => ex.StatusCode == (HttpStatusCode)401): triggers whenever you receive an Unauthorized response
    • //refresh authKey: retrieves the new credentials
    • .Retry(1: performs again the component registration

    You should decorate the AddCosmosStore method like this:

    var settings = new CosmosStoreSettings(databaseName, endpointUri, authKey);
    settingsAction?.Invoke(settings);
    
    var refreshAuthKeyPolicy = Policy
        .Handle<CosmosException>(ex => ex.StatusCode == (HttpStatusCode)401)
        .Retry(1, (response, retryCount) =>
        {
            //refresh authKey
            settings.AuthKey = newAuthKey;
        }
    );
    
    refreshAuthKeyPolicy.Execute(() => services.AddCosmosStore<TEntity>(settings, overriddenContainerName));
    return services;