【发布时间】: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 包含三个变量
- AZURE_CLIENT_ID
- AZURE_CLIENT_SECRET
- 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=<id>, Duration=2108ms)Server failed to authenticate the request. Please refer to the information in the www-authenticate header.RequestId:<id>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:<id>\nTime:2022-10-21T12:15:21.6998519Z"}}}Headers:Server: Microsoft-HTTPAPI/2.0x-ms-request-id: <id>x-ms-error-code: REDACTEDWWW-Authenticate: Bearer authorization_uri=https://login.microsoftonline.com/<tenant_id>/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=<id>, Duration=2349ms)This request is not authorized to perform this operation using this permission.RequestId:<request>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:<id>\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: <id>x-ms-client-request-id: <id>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