【问题标题】:Azure - System Assigned Managed Identities for Function AppAzure - Function App 的系统分配托管标识
【发布时间】:2022-10-24 02:15:35
【问题描述】:

我有一个函数应用程序,需要授予它写入 blob/表存储的权限。我打开了“系统分配的托管标识”,并为其设置了以下权限,范围是我需要访问的存储帐户。

Storage Account Contributor
Storage Blob Data Owner
Storage Table Data Contributor
Storage Queue Data Contributor

更新我删除了 AZURE_CLIENT_ID、AZURE_CLIENT_SECRET 和 AZURE_TENANT_ID,然后收到环境配置错误。我不是在本地运行或调试,而是通过 API 管理触发它。

Executed 'Create' (Failed, Duration=1406ms)EnvironmentCredential authentication unavailable. Environment variables are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/environmentcredential/troubleshoot

^ 上面的链接告诉我应该重新添加这些环境变量,但根据下面 Peter Bon 的回答,我似乎不需要它们

我觉得非常令人困惑的一件事情(因为我在任何地方都找不到很好的文档)是我是 Azure 的 required 包含三个变量

  1. AZURE_CLIENT_ID
  2. AZURE_CLIENT_SECRET
  3. AZURE_TENANT_ID

    我推断需要它们才能真正允许我的函数应用程序访问存储帐户,这起初让我感到困惑,因为如果我只是通过分配的角色明确授予它权限,为什么我还需要完全在我的函数应用程序之外创建一些东西允许它做我已经允许它做的事情?

    不过,我对此的问题是“我如何做到这一点?”如果我需要进行应用注册,回调 URL 应该是什么? API 权限应该是什么?我给了它我最好的猜测,并没有得到令人满意的结果。

    App Registration:
    API permissions -> Microsoft.Graph User.Read
    Authentication -> https://<mydomain>.onmicrosoft.com/.auth/login/aad/callback
                   -> ID Tokens
                   -> Accounts in this organization
    Secrets        -> Generated new secret to use for AZURE_CLIENT_SECRET
    Roles & Admissions -> Cloud application administrator
    

    然后,我将 AZURE_CLIENT_ID 设置为此应用注册的应用 ID,将 AZURE_CLIENT_SECRET 设置为应用注册的机密,将 AZURE_TENANT_ID 设置为我的租户 ID。

    然后在我的代码中,我尝试执行以下操作

    var tableUri = new Uri(string.Format("https://{0}.table.core.windows.net/", storageAccountName));
    var credential = new DefaultAzureCredential(options);
    services.AddScoped(x => new TableServiceClient(tableUri, credential));
    

    访问我的表存储时失败,出现以下错误:

    Executed 'Create' (Failed, Id=&lt;id&gt;, Duration=2108ms)Server failed to authenticate the request. Please refer to the information in the www-authenticate header.RequestId:&lt;id&gt;Time:2022-10-21T12:15:21.6998519ZStatus: 401 (Server failed to authenticate the request. Please refer to the information in the www-authenticate header.)ErrorCode: InvalidAuthenticationInfoContent:{"odata.error":{"code":"InvalidAuthenticationInfo","message":{"lang":"en-US","value":"Server failed to authenticate the request. Please refer to the information in the www-authenticate header.\nRequestId:&lt;id&gt;\nTime:2022-10-21T12:15:21.6998519Z"}}}Headers:Server: Microsoft-HTTPAPI/2.0x-ms-request-id: &lt;id&gt;x-ms-error-code: REDACTEDWWW-Authenticate: Bearer authorization_uri=https://login.microsoftonline.com/&lt;tenant_id&gt;/oauth2/authorize resource_id=https://storage.azure.comDate: Fri, 21 Oct 2022 12:15:21 GMTContent-Length: 279Content-Type: application/json

    如果我将身份验证重定向更新为

    https://storage.azure.com
    

    然后我收到以下错误: Executed 'Create' (Failed, Id=&lt;id&gt;, Duration=2349ms)This request is not authorized to perform this operation using this permission.RequestId:&lt;request&gt;Time:2022-10-21T13:14:29.0955823ZStatus: 403 (Forbidden)ErrorCode: AuthorizationPermissionMismatchContent:{"odata.error":{"code":"AuthorizationPermissionMismatch","message":{"lang":"en-US","value":"This request is not authorized to perform this operation using this permission.\nRequestId:&lt;id&gt;\nTime:2022-10-21T13:14:29.0955823Z"}}}Headers:Cache-Control: no-cacheTransfer-Encoding: chunkedServer: Windows-Azure-Table/1.0,Microsoft-HTTPAPI/2.0x-ms-request-id: &lt;id&gt;x-ms-client-request-id: &lt;id&gt;x-ms-version: REDACTEDX-Content-Type-Options: REDACTEDDate: Fri, 21 Oct 2022 13:14:28 GMTContent-Type: application/json; odata=minimalmetadata; streaming=true; charset=utf-8

    老实说,我现在很困惑,有人可以帮助我了解如何成功设置系统分配的托管身份吗?

    更新答案在 Peter 的建议下想通了。所以,我不是 C# 开发人员,但有编程背景并且正在为这个项目做 devops,另一组正在编写应用程序。我没有意识到他们专门使用了 new EnvironmentCredential();在他们的代码中,因为他们强调始终需要使用 DefaultAzureCredential 但 EnvironmentCredential 强制设置 AZURE_CLIENT_ID。这也解释了我们使用 DefaultAzureCredential 的问题,因为它像您在答案中链接的那样遍历列表,因此它看到 AZURE_CLIENT_ID 已设置,并且即使 MI 具有正确的权限,也不会打扰 MI。

【问题讨论】:

  • 你在这里传递的选项是什么:var credential = new DefaultAzureCredential(options);
  • 我起初尝试什么都不通过。当失败时,我尝试将其设置为 var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = userAssignedClientId });根据文档,但如果我这样做,它似乎完全忽略了我传入的 clientId
  • 主要问题之一是我知道其他开发人员想对此进行调试,所以我相信环境变量应该被允许,这样如果您从 Visual Studio 调试它,它可以获取您的本地凭据,因此在理想的世界中,DefaultAzureCredential 的行为方式与记录的方式相同。即 1. 它查找 env 凭据,然后如果它们不存在则跳过它们 2. 检查托管标识并在存在时使用它

标签: c# azure authentication azure-functions azure-managed-identity


【解决方案1】:

使用托管标识时,您不应提供这些环境变量。它还会破坏不必存储秘密的目的。在这种情况下,它们不是必需的。这只是DefaultAzureCredential 尝试获取有效凭据的众多方式之一。见this section。如果您不提供它们,它将回退尝试使用托管标识。

【讨论】:

  • 当我删除它们时,我收到以下错误 Executed 'Create' (Failed, Duration=1281ms)EnvironmentCredential 身份验证不可用。环境变量未完全配置。有关详细信息,请参阅故障排除指南。 aka.ms/azsdk/net/identity/environmentcredential/troubleshoot
  • 所以这似乎是在告诉我,我需要先配置环境变量,然后才能使用函数应用程序。该链接将我带到一个部分,说我需要添加这三个 ENV 变量。它在该图中检查的第一件事是环境,这让我认为它永远不会检查我是否启用了系统分配的托管身份
  • 好吧,文档指出了这一点:DefaultAzureCredential 尝试按此顺序通过以下机制进行身份验证,成功时停止.因此,如果 env 失败,它应该继续使用托管标识 (MI)。我怀疑 MI 的设置方式可能有问题。您是否尝试过禁用 MI 并重新开始尝试?
  • 我刚才做了确定,但我仍然遇到同样的错误。我想知道我是否在某个地方设置了其他导致我出现问题的东西。我确实配置了 ENV 变量,但它主要是 api 键和端点以及我希望最终转移到 MI 的东西。我可以提供任何其他有助于调试此问题的信息吗?
  • 我也设置了 MICROSOFT_PROVIDER_AUTHENTICATION_SECRET 因为我使用它来处理 API 管理和功能应用程序之间的身份验证,你认为这可能会导致问题吗?
猜你喜欢
  • 1970-01-01
  • 2021-07-27
  • 2021-11-20
  • 2021-07-17
  • 1970-01-01
  • 2021-01-26
  • 2023-02-22
  • 1970-01-01
  • 2020-09-12
相关资源
最近更新 更多