Azure / Azure/azure-functions-host

[BUG] Attempt to retrieve certificate with Managed Identity in Azure function results in access denied error

Open
#9,460 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
2k
Forks
482
Avg merge
2d 10h
Merged PRs (30d)
36

Description

# Issue Transfer

This issue has been transferred from the Azure SDK for .NET repository, [#38162](https://github.com/Azure/azure-sdk-for-net/issues/38162).

### Please be aware that @mlhickey is the author of the original issue and include them for any questions or replies.

## Details

### Library name and version

Azure.Security.KeyVault.Certificates 4.5.1, Azure.Security.KeyVault.Secrets 4.5.0

### Describe the bug

Azure function written in C# running under premium EP1 service plan. Updated to current libraries as identitifed. Secret retrieval work as previous/expected locally and published. Certificate retrieval works locally , e.g.:

```
public X509Certificate2? GetCertificate(string certificateName)
{
try
{
var certificate = _cclient.DownloadCertificate(certificateName);
return certificate?.Value;
}
catch (Exception ex)
{
throw new Exception($"Certificate retrieval failed: {ex.Message}");
}
}
```
But when published and executing in MI context which has all necessary KV perms the initial result was:

```
2023-08-11T14:15:23.472 [Error] Executed 'ProvisionLauncher' (Failed, Id=cad6d631-db7d-4995-b9d4-63ebfb66ca4c, Duration=6256ms)
The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating.
```

Found an article that discussed requiring:

`WEBSITE_LOAD_USER_PROFILE = 1`

to be added to the config. Doing so moved to a new error:

```
2023-08-11T14:20:36.794 [Error] Executed 'ProvisionLauncher' (Failed, Id=07aafd76-11fd-4245-848a-456054e562db, Duration=8199ms)
Access to the path 'C:\Program Files (x86)\SiteExtensions\Functions\4.23.0\64bit\.IdentityService' is denied.
```

because that path doesn't exist. The function is running in a EP1 plan so to my understanding the profile bits should be valid.

### Expected behavior

Certificate returned sans error

### Actual behavior

Fails with:

```
2023-08-11T14:20:36.794 [Error] Executed 'ProvisionLauncher' (Failed, Id=07aafd76-11fd-4245-848a-456054e562db, Duration=8199ms)
Access to the path 'C:\Program Files (x86)\SiteExtensions\Functions\4.23.0\64bit\.IdentityService' is denied.
```

### Reproduction Steps

Create Azure function with minimal code required for certificate retrieval, e.g.
DI service:
```
private static void ConfigureKeyVaultCertificate(IServiceCollection services)
{
services.AddTransient(provider =>
{
var configuration = provider.GetService();
var endpoint = configuration["KeyVault:BaseUri"];
if (string.IsNullOrEmpty(endpoint))
throw new ArgumentNullException(nameof(endpoint), "KeyVault:BaseUri can not be blank");

var endpointUri = new Uri(endpoint);
var credentials = new DefaultAzureCredential(includeInteractiveCredentials: true);
return new CertificateClient(vaultUri: endpointUri, credential: credentials);
});
}
```
Retrieval method:
```
public X509Certificate2? GetCertificate(string certificateName)
{
try
{
var certificate = _cclient.DownloadCertificate(certificateName);
return certificate?.Value;
}
catch (Exception ex)
{
throw new Exception($"Certificate retrieval failed: {ex.Message}");
}
}
```

### Environment

Azure function version 4

C:\home\LogFiles\Application\Functions\Function\ProvisionLauncher>dotnet --info
.NET SDK:
Version: 7.0.305
Commit: 98e1b6c381

Runtime Environment:
OS Name: Windows
OS Version: 10.0.14393
OS Platform: Windows
RID: win10-x86
Base Path: C:\Program Files (x86)\dotnet\sdk\7.0.305\

Host:
Version: 7.0.8
Architecture: x86
Commit: 4b0550942d

.NET SDKs installed:
1.1.14 [C:\Program Files (x86)\dotnet\sdk]
2.1.526 [C:\Program Files (x86)\dotnet\sdk]
2.2.109 [C:\Program Files (x86)\dotnet\sdk]
3.1.118 [C:\Program Files (x86)\dotnet\sdk]
3.1.426 [C:\Program Files (x86)\dotnet\sdk]
5.0.408 [C:\Program Files (x86)\dotnet\sdk]
6.0.408 [C:\Program Files (x86)\dotnet\sdk]
6.0.411 [C:\Program Files (x86)\dotnet\sdk]
7.0.203 [C:\Program Files (x86)\dotnet\sdk]
7.0.305 [C:\Program Files (x86)\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.30 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.14 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.30 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.14 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.3 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.32 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.17 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.16 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.19 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.5 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.8 [C:\Program Files (x86)\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 1.0.16 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 1.1.13 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.0.9 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.30 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.14 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.3 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.32 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.17 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.16 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.19 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.5 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.8 [C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App]

Other architectures found:
x64 [C:\Program Files (x86)\dotnet]

Environment variables:
Not set

global.json file:
Not found

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the minimal Azure Function using ConfigureKeyVaultCertificate, DefaultAzureCredential, CertificateClient, and GetCertificate. Compare local and published Managed Identity behavior on the EP1 plan, focusing on the WEBSITE_LOAD_USER_PROFILE setting and the reported .IdentityService access-denied path. Done means DownloadCertificate returns the certificate successfully in the published function.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, csharp
Domain
backend, cloud
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.