简体   繁体   English

如何从 Azure Functions (v2) 使用 Azure Key Vault

[英]How to use Azure Key Vault from Azure Functions (v2)

I am tring to use Azure Key Vault from Azure Functions (v2);我正在尝试使用 Azure Functions (v2) 中的 Azure Key Vault;
When I run local it works, but when I publish this code to Azure:当我在本地运行时,它可以工作,但是当我将此代码发布到 Azure 时:

try
{
    var vault_url = "https://mykeyvault.vault.azure.net/";
    var azureServiceTokenProvider = new AzureServiceTokenProvider();
    var kvClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback), client);

    fbAppSecret = (await kvClient.GetSecretAsync(vault_url, "facebook-appid-secret-...")).Value;
}
catch (Exception ex)
{
    error = ex.ToString();
}

It is giving an Exception that contains this (Please check that you are running on an Azure resource that has MSI setup.):它给出了一个包含此内容的异常(请检查您是否在具有 MSI 设置的 Azure 资源上运行。):

Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connectionstring: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/66ad737e-d8cc-4ab3-abf0-feab50685d13. Exception Message: Tried the following 3 methods to get an access token, but none of them worked.
Parameters: Connectionstring: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/66ad737e-d8cc-4ab3-abf0-feab50685d13. Exception Message: Tried to get token using Managed Service Identity. Unable to connect to the Managed Service Identity (MSI) endpoint. Please check that you are running on an Azure resource that has MSI setup.
Parameters: Connectionstring: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/66ad737e-d8cc-4ab3-abf0-feab50685d13. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Visual Studio Token provider file not found at "D:\local\LocalAppData\.IdentityService\AzureServiceAuth\tokenprovider.json"
Parameters: Connectionstring: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/66ad737e-d8cc-4ab3-abf0-feab50685d13. Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. 'az' is not recognized as an internal or external command,
operable program or batch file.


   at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.<GetAccessTokenAsyncImpl>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Azure.KeyVault.KeyVaultCredential.<PostAuthenticate>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Azure.KeyVault.KeyVaultCredential.<ProcessHttpRequestAsync>d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Azure.KeyVault.KeyVaultClient.<GetSecretWithHttpMessagesAsync>d__65.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Azure.KeyVault.KeyVaultClientExtensions.<GetSecretAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at ApelosUrgentesFunctionApp.MyFunctions.<Run>d__1.MoveNext() in C:\Users\tonyv\source\repos\siteApelosUrgentes\ApelosUrgentesFunctionApp\MyFunctions.cs:line 50

Then I found MSI means Managed Service identity and can be enabled on the Azure Functions Portal:然后我发现 MSI 意味着托管服务标识,可以在 Azure Functions 门户上启用:

托管服务身份

But after enabled it, there is another Exception:但是启用它后,还有另一个异常:

Microsoft.Azure.KeyVault.Models.KeyVaultErrorException: Access denied
   at Microsoft.Azure.KeyVault.KeyVaultClient.<GetSecretWithHttpMessagesAsync>d__65.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Azure.KeyVault.KeyVaultClientExtensions.<GetSecretAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at ApelosUrgentesFunctionApp.MyFunctions.<Run>d__1.MoveNext() in C:\Users\tonyv\source\repos\siteApelosUrgentes\ApelosUrgentesFunctionApp\MyFunctions.cs:line 50

I added the Azure Functions App as Reader, then later as Owner, but still getting我将 Azure Functions App 添加为 Reader,然后添加为 Owner,但仍然得到

I added the Azure Functions App as Owner, but still getting我将 Azure Functions 应用程序添加为所有者,但仍然得到

Microsoft.Azure.KeyVault.Models.KeyVaultErrorException: Access denied
at Microsoft.Azure.KeyVault.KeyVaultClient.<GetSecretWithHttpMessagesAsync>d__65.MoveNext()

综合管理

I also added all the access policies, but still getting Access Denied我还添加了所有访问策略,但仍然拒绝访问

美联社 AP2

Checked Kudu, AppSettings:检查 Kudu,AppSettings:

https://myfunctionapp.scm.azurewebsites.net/api/settings https://myfunctionapp.scm.azurewebsites.net/api/settings

{"deployment_branch":"master","SCM_TRACE_LEVEL":"1","SCM_COMMAND_IDLE_TIMEOUT":"60","SCM_LOGSTREAM_TIMEOUT":"1800","SCM_BUILD_ARGS":"","aspnet:PortableCompilationOutput":"true","aspnet:PortableCompilationOutputSnapshotType":"Microsoft.Web.Compilation.Snapshots.SnapshotHelper, Microsoft.Web.Compilation.Snapshots, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","aspnet:DisableFcnDaclRead":"true","SCM_GIT_USERNAME":"windowsazure","SCM_GIT_EMAIL":"windowsazure","webpages:Version":"3.0.0.0","webpages:Enabled":"true","webactivator:assembliesToScan":"Kudu.Services.Web","MSDEPLOY_RENAME_LOCKED_FILES":"1","FUNCTIONS_EXTENSION_VERSION":"beta","ScmType":"None","WEBSITE_AUTH_ENABLED":"False","REMOTEDEBUGGINGVERSION":"15.0.26730.8","WEBSITE_DISABLE_MSI":"false","AzureWebJobsDashboard":"DefaultEndpointsProtocol=https;AccountName=functionapp;AccountKey=xQ","WEBSITE_CONTENTAZUREFILECONNECTIONSTRING":"DefaultEndpointsProtocol=https;AccountName=functionapp;AccountKey=xq","WEBSITE_CONTENTSHARE":"apelosurgentesfunctionapp","WEBSITE_SLOT_NAME":"Production","AzureWebJobsStorage":"DefaultEndpointsProtocol=https;AccountName=functionapp;AccountKey=xq","WEBSITE_SITE_NAME":"FunctionApp"}

How to solve this?如何解决这个问题?

One detail I found in your pictures is in Access Policies, you have "application + application" under your Service Principal.我在您的图片中发现的一个细节是在访问策略中,您的服务主体下有“应用程序 + 应用程序”。

Are you able to remove the service principal and add it back with only the app in the Service Principal, leaving Authorized App blank您是否能够删除服务主体并仅使用服务主体中的应用程序将其添加回来,而将授权应用程序留空

As seen in this Article:如本文所示:

https://docs.microsoft.com/en-us/azure/key-vault/key-vault-secure-your-key-vault#authentication-using-azure-active-directory https://docs.microsoft.com/en-us/azure/key-vault/key-vault-secure-your-key-vault#authentication-using-azure-active-directory

When you use the authorized applications is for apps that must access on behalf of signed in users, thus An application working on behalf of itself does not works as expected.当您使用授权应用程序时,必须代表登录用户访问的应用程序,因此代表自身工作的应用程序无法按预期工作。

Why does it works out of the box on localhost, but on published version I have to follow all those steps?为什么它在本地主机上开箱即用,但在已发布的版本中我必须遵循所有这些步骤?

You could refer to Azure Services Authentication Extension to get more information about how it works on the localhost.您可以参考Azure 服务身份验证扩展以获取有关它如何在 localhost 上工作的更多信息。 It use the your login account and your account has the access to the Azure key vault resource.它使用您的登录帐户,您的帐户可以访问 Azure Key Vault 资源。

在此处输入图片说明

If you publish it to Azure function, you could use the Azure MSI function, it will registry the Azure AD application automatically.Then we also need to assgin the permisson to access the KeyVault.如果发布到Azure 函数,可以使用Azure MSI 函数,它会自动注册Azure AD 应用程序。然后我们还需要分配访问KeyVault 的权限。

I also test it on my side,it works correctly.我也在我这边进行了测试,它工作正常。 Please make sure that MSI is enabled correctly in your case.请确保在您的情况下正确启用了 MSI。 You could check the MSI_SECRET and MSI_ENDPOINT with Azure kudu tool.您可以使用 Azure kudu 工具检查MSI_SECRETMSI_ENDPOINT

Please use the AzureServiceTokenProvider's PrincipalUsed property to check what AppId is being used to authenticate, or in other words, what is the Managed Service Identity being used.请使用 AzureServiceTokenProvider 的PrincipalUsed属性来检查正在使用什么AppId进行身份验证,或者换句话说,正在使用的托管服务标识是什么。 The fact that you are getting "Access Denied" means that it was possible to get the access token, but the MSI does not have access to Key Vault.您收到“拒绝访问”这一事实意味着可以获取访问令牌,但 MSI 无权访问 Key Vault。 You did grant access to a service principal, but most likely, not to the right one.您确实授予了对服务主体的访问权限,但很可能不是授予正确的服务主体。 Use the AppId returned in PrincipalUsed to search for "Service Principal" using Key Vault "Access Policy".使用PrincipalUsed 中返回的AppId使用 Key Vault“访问策略”搜索“服务主体”。

This is the current easy way with Azure Functions https://docs.microsoft.com/en-gb/azure/app-service/app-service-key-vault-references这是 Azure Functions 当前最简单的方法https://docs.microsoft.com/en-gb/azure/app-service/app-service-key-vault-references

eg specific version @Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931)例如特定版本@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931)

eg get latest version (note: trailing slash!) @Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/)例如获取最新版本(注意:尾部斜杠!) @Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM